diff --git a/.cspell.json b/.cspell.json index b138b5986..8a68fa8cc 100644 --- a/.cspell.json +++ b/.cspell.json @@ -13,7 +13,9 @@ "npm" ], "ignorePaths": [ + ".pylintrc", "requirements.txt", + "requirements-dev.txt", "maven-wrapper.jar", ".cspell.json", ".gitignore", diff --git a/.editorconfig b/.editorconfig index e4e4be744..3aa6398c7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -26,6 +26,7 @@ max_line_length = 80 [*.py] indent_size = 4 +max_line_length = 100 [*.{json,xml,html,ejs}] indent_size = 4 diff --git a/.pylintrc b/.pylintrc index 5bdea6e75..7c60d3a2d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,364 +1,642 @@ [MAIN] -# Specify a configuration file. -#rcfile= +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Clear in-memory caches upon conclusion of linting. Useful if running pylint +# in a server-like mode. +clear-cache-post-run=no + +# Load and enable all available extensions. Use --list-extensions to see a list +# all available extensions. +#enable-all-extensions= + +# In error mode, messages with a category besides ERROR or FATAL are +# suppressed, and no reports are done by default. Error mode is compatible with +# disabling specific errors. +#errors-only= + +# Always return a 0 (non-error) status code, even if lint errors are found. +# This is primarily useful in continuous integration scripts. +#exit-zero= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-allow-list= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. (This is an alternative name to extension-pkg-allow-list +# for backward compatibility.) +extension-pkg-whitelist= + +# Return non-zero exit code if any of these messages/categories are detected, +# even if score is above --fail-under value. Syntax same as enable. Messages +# specified are enabled, while categories only check already-enabled messages. +fail-on= + +# Specify a score threshold under which the program will exit with error. +fail-under=10 + +# Interpret the stdin as a python script, whose filename needs to be passed as +# the module_or_package argument. +#from-stdin= + +# Files or directories to be skipped. They should be base names, not paths. +ignore=CVS, compat.py, __main__.py, __init__.py + +# Add files or directories matching the regular expressions patterns to the +# ignore-list. The regex matches against paths and can be in Posix or Windows +# format. Because '\\' represents the directory delimiter on Windows systems, +# it can't be used as an escape character. +ignore-paths= + +# Files or directories matching the regular expression patterns are skipped. +# The regex matches against base names, not paths. The default value ignores +# Emacs file locks +ignore-patterns=^\.# + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= -# Files or directories to be skipped. They should be base names, not -# paths. -ignore=compat.py, __main__.py +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use, and will cap the count on Windows to +# avoid hangs. +jobs=1 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python module names) to load, +# usually to register additional checkers. +load-plugins= # Pickle collected data for later comparisons. persistent=yes -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= +# Minimum Python version to use for version dependent checks. Will default to +# the version used to run pylint. +py-version=3.10 -# Use multiple processes to speed up Pylint. -jobs=1 +# Discover python modules and packages in the file system subtree. +recursive=no + +# Add paths to the list of the source roots. Supports globbing patterns. The +# source root is an absolute path or a path relative to the current working +# directory used to determine a package namespace for modules located under the +# source root. +source-roots= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-allow-list= +# In verbose mode, extra non-checker-related info will be displayed. +#verbose= -# Allow optimization of some AST trees. This will activate a peephole AST -# optimizer, which will apply various small optimizations. For instance, it can -# be used to obtain the result of joining multiple strings with the addition -# operator. Joining a lot of strings can lead to a maximum recursion error in -# Pylint and this flag can prevent that. It has one side effect, the resulting -# AST will be different than the one from reality. -optimize-ast=no +[BASIC] -[MESSAGES CONTROL] +# Naming style matching correct argument names. +argument-naming-style=snake_case -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= +# Regular expression matching correct argument names. Overrides argument- +# naming-style. If left empty, argument names will be checked with the set +# naming style. +#argument-rgx= -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. See also the "--disable" option for examples. -#enable= +# Naming style matching correct attribute names. +attr-naming-style=snake_case -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=W0107,W0201,R0913,R0902,E0401,C0103,E0611,R0914,C0321,W1203 +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. If left empty, attribute names will be checked with the set naming +# style. +#attr-rgx= +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata -[REPORTS] +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +bad-names-rgxs= -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text +# Naming style matching correct class attribute names. +class-attribute-naming-style=any -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. If left empty, class attribute names will be checked +# with the set naming style. +#class-attribute-rgx= -# Tells whether to display a full report or only the messages -reports=no +# Naming style matching correct class constant names. +class-const-naming-style=UPPER_CASE -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) +# Regular expression matching correct class constant names. Overrides class- +# const-naming-style. If left empty, class constant names will be checked with +# the set naming style. +#class-const-rgx= -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= +# Naming style matching correct class names. +class-naming-style=PascalCase +# Regular expression matching correct class names. Overrides class-naming- +# style. If left empty, class names will be checked with the set naming style. +#class-rgx= -[BASIC] +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. If left empty, constant names will be checked with the set naming +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. If left empty, function names will be checked with the set +# naming style. +#function-rgx= -# List of builtins function names that should not be used, separated by a comma -bad-functions=apply,reduce +# Good variable names which should always be accepted, separated by a comma. +good-names=e, + i, + j, + k, + n, + ex, + ou, + s3, + Run, + _ -# Good variable names which should always be accepted, separated by a comma -good-names=e,i,j,k,n,ex,Run,_ +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +good-names-rgxs= -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. If left empty, inline iteration names will be checked +# with the set naming style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. If left empty, method names will be checked with the set naming style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. If left empty, module names will be checked with the set naming style. +#module-rgx= # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= -# Include a hint for the correct naming format with invalid-name -include-naming-hint=yes +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ -# Regular expression matching correct function names -function-rgx=[a-z_][a-z0-9_]{2,50}$ +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty -# Naming hint for function names -function-name-hint=[a-z_][a-z0-9_]{2,30}$ +# Regular expression matching correct type alias names. If left empty, type +# alias names will be checked with the set naming style. +#typealias-rgx= -# Regular expression matching correct variable names -variable-rgx=[a-z_][a-z0-9_]{0,50}$ +# Regular expression matching correct type variable names. If left empty, type +# variable names will be checked with the set naming style. +#typevar-rgx= -# Naming hint for variable names -variable-name-hint=[a-z_][a-z0-9_]{2,30}$ +# Naming style matching correct variable names. +variable-naming-style=snake_case -# Regular expression matching correct constant names -const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$ +# Regular expression matching correct variable names. Overrides variable- +# naming-style. If left empty, variable names will be checked with the set +# naming style. +#variable-rgx= -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ -# Regular expression matching correct attribute names -attr-rgx=[a-z_][a-z0-9_]{1,50}$ +[CLASSES] -# Naming hint for attribute names -attr-name-hint=[a-z_][a-z0-9_]{2,30}$ +# Warn about protected attribute access inside special methods +check-protected-access-in-special-methods=no -# Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{0,50}$ +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp, + asyncSetUp, + __post_init__ -# Naming hint for argument names -argument-name-hint=[a-z_][a-z0-9_]{2,30}$ +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ +[DESIGN] -# Regular expression matching correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ +# List of regular expressions of class ancestor names to ignore when counting +# public methods (see R0903) +exclude-too-few-public-methods= -# Naming hint for class names -class-name-hint=[A-Z_][a-zA-Z0-9]+$ +# List of qualified class names to ignore when counting class parents (see +# R0901) +ignored-parents= -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ +# Maximum number of arguments for function / method. +max-args=12 -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ +# Maximum number of attributes for a class (see R0902). +max-attributes=12 -# Regular expression matching correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr=5 -# Naming hint for method names -method-name-hint=[a-z_][a-z0-9_]{2,30}$ +# Maximum number of branch for function / method body. +max-branches=12 -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=.* +# Maximum number of locals for function / method body. +max-locals=15 -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when caught. +# overgeneral-exceptions=builtins.BaseException,builtins.Exception +overgeneral-exceptions= [FORMAT] -# Maximum number of characters on a single line. -max-line-length=190 +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no -# List of optional constructs for which whitespace checking is disabled -no-space-check=trailing-comma,dict-separator -# Maximum number of lines in a module -max-module-lines=1000 +[IMPORTS] -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 +# Allow explicit reexports by alias from a package __init__. +allow-reexport-from-package=no -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec,UserDict + +# Output a graph (.gv or any supported image format) of external dependencies +# to the given file (report RP0402 must not be disabled). +ext-import-graph= + +# Output a graph (.gv or any supported image format) of all (i.e. internal and +# external) dependencies to the given file (report RP0402 must not be +# disabled). +import-graph= + +# Output a graph (.gv or any supported image format) of internal dependencies +# to the given file (report RP0402 must not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= [LOGGING] +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old + # Logging modules to check that the string format arguments are in logging -# function parameter format +# function parameter format. logging-modules=logging +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, +# UNDEFINED. +confidence=HIGH, + CONTROL_FLOW, + INFERENCE, + INFERENCE_FAILURE, + UNDEFINED + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then re-enable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + missing-function-docstring, + missing-class-docstring, + too-few-public-methods, + import-error, + fixme, + similarities + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=c-extension-no-member + + +[METHOD_ARGS] + +# List of qualified names (i.e., library.method) which require a timeout +# parameter e.g. 'requests.api.get,requests.api.post' +timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request + + [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX +notes=FIXME, + XXX, + TODO +# Regular expression of note tags to take in consideration. +notes-rgx= -[SIMILARITIES] -# Minimum lines number of a similarity. -# Temp 500 until we merge initial_commit into shared codebase. -min-similarity-lines=500 +[REFACTORING] -# Ignore comments when computing similarities. -ignore-comments=yes +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 -# Ignore docstrings when computing similarities. -ignore-docstrings=yes +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit,argparse.parse_error -# Ignore imports when computing similarities. -ignore-imports=yes +[REPORTS] -[SPELLING] +# Python expression which should return a score less than or equal to 10. You +# have access to the variables 'fatal', 'error', 'warning', 'refactor', +# 'convention', and 'info' which contain the number of messages in each +# category, as well as 'statement' which is the total number of statements +# analyzed. This score is used by the global evaluation report (RP0004). +evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +msg-template= -# List of comma separated words that should not be checked. -spelling-ignore-words= +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +#output-format= -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= +# Tells whether to display a full report or only the messages. +reports=no -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no +# Activate the evaluation score. +score=yes -[TYPECHECK] +[SIMILARITIES] -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes +# Comments are removed from the similarity computation +ignore-comments=yes -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis -ignored-modules=six.moves +# Docstrings are removed from the similarity computation +ignore-docstrings=yes -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject +# Imports are removed from the similarity computation +ignore-imports=yes -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent,objects,DoesNotExist,md5,sha1,sha224,sha256,sha384,sha512 +# Signatures are removed from the similarity computation +ignore-signatures=yes +# Minimum lines number of a similarity. +min-similarity-lines=20 -[VARIABLES] -# Tells whether we should check for unused import in __init__ files. -init-import=no +[SPELLING] -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_|dummy|ignore +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= +# Spelling dictionary name. No available dictionaries : You need to install +# both the python package and the system dependency for enchant to work.. +spelling-dict= -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb +# List of comma separated words that should be considered directives if they +# appear at the beginning of a comment and should not be checked. +spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: +# List of comma separated words that should not be checked. +spelling-ignore-words= -[CLASSES] +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +spelling-store-unknown-words=no -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs +[STRING] -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=no +# This flag controls whether the implicit-str-concat should generate a warning +# on implicit string concatenation in sequences defined over several lines. +check-str-concat-over-line-jumps=no -[DESIGN] -# Maximum number of arguments for function / method -max-args=5 +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= -# Maximum number of locals for function / method body -max-locals=15 +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes -# Maximum number of return / yield for function / method body -max-returns=6 +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes -# Maximum number of branch for function / method body -max-branches=12 +# List of symbolic message names to ignore for Mixin members. +ignored-checks-for-mixins=no-member, + not-async-context-manager, + not-context-manager, + attribute-defined-outside-init -# Maximum number of statements in function / method body -max-statements=40 +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace -# Maximum number of parents for a class (see R0901). -max-parents=6 +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes -# Maximum number of attributes for a class (see R0902). -max-attributes=7 +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 -# Minimum number of public methods for a class (see R0903). -min-public-methods=0 +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 +# Regex pattern to define which classes are considered mixins. +mixin-class-rgx=.*[Mm]ixin +# List of decorators that change the signature of a decorated function. +signature-mutators= -[IMPORTS] -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec,UserDict +[VARIABLES] -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= +# List of names allowed to shadow builtins +allowed-redefined-builtins=id -[EXCEPTIONS] +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io diff --git a/Makefile b/Makefile index b0fbfb745..eb749304f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ init: - pip install -r requirements.txt + pip install -r requirements.txt -r requirements-dev.txt test: # Run unit tests diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 000000000..145b83b9a --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,7 @@ +cfn-lint==0.78.2 +isort==5.12.0 +mock==5.1.0 +pylint==2.17.4 +pytest~=7.4.0 +tox==3.28.0 +yamllint==1.32.0 diff --git a/requirements.txt b/requirements.txt index 710f186f6..4702d9854 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,5 @@ -astroid==2.11.7 -boto3==1.26.133 -botocore==1.29.133 -cfn-lint==0.77.2 -docutils==0.16 -isort==5.11.4 -mock==5.0.1 -pylint==2.13.9 -pytest==7.2.0 -pyyaml~=5.4 +astroid==2.15.6 +boto3==1.28.8 +botocore==1.31.8 +pyyaml~=6.0.1 schema==0.7.5 -tox==3.28.0 -yamllint==1.29.0 diff --git a/samples/sample-rdk-rules/requirements.txt b/samples/sample-rdk-rules/requirements.txt index 51a7b58ac..6b3a0c44e 100644 --- a/samples/sample-rdk-rules/requirements.txt +++ b/samples/sample-rdk-rules/requirements.txt @@ -1,3 +1,3 @@ s3==3.0.0 -boto3==1.24.59 +boto3==1.28.8 argparse==1.4.0 diff --git a/src/lambda_codebase/account/handler.py b/src/lambda_codebase/account/handler.py index b78f3ea44..4dfb47b13 100644 --- a/src/lambda_codebase/account/handler.py +++ b/src/lambda_codebase/account/handler.py @@ -18,16 +18,16 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get( + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( "PhysicalResourceId", "NOT_YET_CREATED"), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/account/main.py b/src/lambda_codebase/account/main.py index 7d75f5f5f..57f15784a 100644 --- a/src/lambda_codebase/account/main.py +++ b/src/lambda_codebase/account/main.py @@ -1,6 +1,5 @@ # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 - """ The Account main that is called when ADF is installed to initially create the deployment account if required. @@ -168,7 +167,7 @@ def wait_on_account_creation(request_id: str) -> Tuple[AccountId, bool]: ) if account_status["CreateAccountStatus"]["State"] == "FAILED": reason = account_status["CreateAccountStatus"]["FailureReason"] - raise Exception(f"Failed to create account because {reason}") + raise RuntimeError(f"Failed to create account because {reason}") if account_status["CreateAccountStatus"]["State"] == "IN_PROGRESS": LOGGER.info( "Account creation still in progress, waiting.. " diff --git a/src/lambda_codebase/account_bootstrap.py b/src/lambda_codebase/account_bootstrap.py index 7ac61ccb6..d59cef9f2 100644 --- a/src/lambda_codebase/account_bootstrap.py +++ b/src/lambda_codebase/account_bootstrap.py @@ -59,8 +59,12 @@ def configure_generic_account(sts, event, region, role): region, role, ) - kms_arn = parameter_store_deployment_account.fetch_parameter(f'/cross_region/kms_arn/{region}') - bucket_name = parameter_store_deployment_account.fetch_parameter(f'/cross_region/s3_regional_bucket/{region}') + kms_arn = parameter_store_deployment_account.fetch_parameter( + f'/cross_region/kms_arn/{region}', + ) + bucket_name = parameter_store_deployment_account.fetch_parameter( + f'/cross_region/s3_regional_bucket/{region}', + ) except (ClientError, ParameterNotFoundError): raise GenericAccountConfigureError( f'Account {event["account_id"]} cannot yet be bootstrapped ' @@ -69,7 +73,10 @@ def configure_generic_account(sts, event, region, role): ) from None parameter_store_target_account.put_parameter('kms_arn', kms_arn) parameter_store_target_account.put_parameter('bucket_name', bucket_name) - parameter_store_target_account.put_parameter('deployment_account_id', event['deployment_account_id']) + parameter_store_target_account.put_parameter( + 'deployment_account_id', + event['deployment_account_id'], + ) def configure_master_account_parameters(event): @@ -78,10 +85,22 @@ def configure_master_account_parameters(event): deployment_account_id then updates the main deployment region with that same value """ - parameter_store_master_account_region = ParameterStore(os.environ["AWS_REGION"], boto3) - parameter_store_master_account_region.put_parameter('deployment_account_id', event['account_id']) - parameter_store_deployment_account_region = ParameterStore(event['deployment_account_region'], boto3) - parameter_store_deployment_account_region.put_parameter('deployment_account_id', event['account_id']) + parameter_store_master_account_region = ParameterStore( + os.environ["AWS_REGION"], + boto3, + ) + parameter_store_master_account_region.put_parameter( + 'deployment_account_id', + event['account_id'], + ) + parameter_store_deployment_account_region = ParameterStore( + event['deployment_account_region'], + boto3, + ) + parameter_store_deployment_account_region.put_parameter( + 'deployment_account_id', + event['account_id'], + ) def configure_deployment_account_parameters(event, role): diff --git a/src/lambda_codebase/account_processing/configure_account_alias.py b/src/lambda_codebase/account_processing/configure_account_alias.py index 243497166..a8dafefbc 100644 --- a/src/lambda_codebase/account_processing/configure_account_alias.py +++ b/src/lambda_codebase/account_processing/configure_account_alias.py @@ -37,11 +37,12 @@ def create_account_alias(account, iam_client): iam_client.create_account_alias(AccountAlias=account.get("alias")) except iam_client.exceptions.EntityAlreadyExistsException as error: LOGGER.error( - f"The account alias {account.get('alias')} already exists." + "The account alias %s already exists." "The account alias must be unique across all Amazon Web Services " "products. Refer to " "https://docs.aws.amazon.com/IAM/latest/UserGuide/" - "console_account-alias.html#AboutAccountAlias" + "console_account-alias.html#AboutAccountAlias", + account.get('alias'), ) raise error diff --git a/src/lambda_codebase/account_processing/register_account_for_support.py b/src/lambda_codebase/account_processing/register_account_for_support.py index 34f50c399..eb088ecb3 100644 --- a/src/lambda_codebase/account_processing/register_account_for_support.py +++ b/src/lambda_codebase/account_processing/register_account_for_support.py @@ -29,7 +29,9 @@ class SupportLevel(Enum): class Support: # pylint: disable=R0904 """Class used for accessing AWS Support API""" - _config = Config(retries=dict(max_attempts=30)) + _config = Config(retries={ + "max_attempts": 30, + }) def __init__(self, role): self.client = role.client( @@ -119,7 +121,11 @@ def set_support_level_for_account( account.get("account_full_name"), account_id, ) - self._enable_support_for_account(account, account_id, desired_level) + self._enable_support_for_account( + account, + account_id, + desired_level, + ) else: LOGGER.error( @@ -142,8 +148,8 @@ def _enable_support_for_account( support for the account specified by account_id. :param account: Instance of Account class - :param account_id: AWS Account ID, of the account that will have support - configured + :param account_id: AWS Account ID, of the account that will have + support configured :param desired_level: Desired Support Level :return: Void diff --git a/src/lambda_codebase/account_processing/requirements.txt b/src/lambda_codebase/account_processing/requirements.txt index e51b024d3..81d4d5270 100644 --- a/src/lambda_codebase/account_processing/requirements.txt +++ b/src/lambda_codebase/account_processing/requirements.txt @@ -1,3 +1,3 @@ -aws-xray-sdk==2.11.0 -pyyaml>=5.4.1 +aws-xray-sdk==2.12.0 +pyyaml~=6.0.1 wrapt==1.14.1 # https://github.com/aws/aws-lambda-builders/issues/302 diff --git a/src/lambda_codebase/account_processing/tests/test_account_alias.py b/src/lambda_codebase/account_processing/tests/test_account_alias.py index 63e90158c..3ee0a988d 100644 --- a/src/lambda_codebase/account_processing/tests/test_account_alias.py +++ b/src/lambda_codebase/account_processing/tests/test_account_alias.py @@ -72,7 +72,11 @@ def test_account_alias_when_nonunique(self): stubber.add_client_error( 'create_account_alias', 'EntityAlreadyExistsException', - f"An error occurred (EntityAlreadyExists) when calling the CreateAccountAlias operation: The account alias {test_account.get('alias')} already exists." + ( + "An error occurred (EntityAlreadyExists) when calling the " + "CreateAccountAlias operation: The account alias " + f"{test_account.get('alias')} already exists." + ), ) stubber.activate() diff --git a/src/lambda_codebase/cross_region_bucket/handler.py b/src/lambda_codebase/cross_region_bucket/handler.py index 6a9ebc624..019b6d625 100644 --- a/src/lambda_codebase/cross_region_bucket/handler.py +++ b/src/lambda_codebase/cross_region_bucket/handler.py @@ -7,8 +7,8 @@ """ try: - from main import lambda_handler # pylint: disable=unused-import -except Exception as err: # pylint: disable=broad-except + from main import lambda_handler # pylint: disable=unused-import +except Exception as err: # pylint: disable=broad-except import os import logging from urllib.request import Request, urlopen @@ -18,17 +18,17 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get( + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( "PhysicalResourceId", "NOT_YET_CREATED", ), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/event.py b/src/lambda_codebase/event.py index a9b9b0417..7ae2ad5c1 100644 --- a/src/lambda_codebase/event.py +++ b/src/lambda_codebase/event.py @@ -19,6 +19,8 @@ class Event: """ Class for structuring the Event in Step Functions """ + + # pylint: disable=too-many-instance-attributes def __init__(self, event, parameter_store, organizations, account_id): self.parameter_store = parameter_store self.config = ast.literal_eval( diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/determine_default_branch.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/determine_default_branch.py index 7375dc63e..39faed35d 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/determine_default_branch.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/determine_default_branch.py @@ -12,6 +12,8 @@ delete, ) +# pylint: disable=invalid-name + PhysicalResourceId = str ResponseData = TypedDict("ResponseData", { "DefaultBranchName": str, @@ -81,7 +83,10 @@ def determine_default_branch_name(repo_name) -> str: @create() -def create_(event: Mapping[str, Any], _context: Any) -> Tuple[Union[None, PhysicalResourceId], ResponseData]: +def create_( + event: Mapping[str, Any], + _context: Any, +) -> Tuple[Union[None, PhysicalResourceId], ResponseData]: create_event = CreateEvent(**event) repo_name = repo_arn_to_name(create_event.ResourceProperties.RepositoryArn) default_branch_name = determine_default_branch_name(repo_name) @@ -94,7 +99,10 @@ def create_(event: Mapping[str, Any], _context: Any) -> Tuple[Union[None, Physic @update() -def update_(event: Mapping[str, Any], _context: Any) -> Tuple[PhysicalResourceId, ResponseData]: #pylint: disable=R0912, R0915 +def update_( + event: Mapping[str, Any], + _context: Any, +) -> Tuple[PhysicalResourceId, ResponseData]: #pylint: disable=R0912, R0915 update_event = UpdateEvent(**event) repo_name = repo_arn_to_name(update_event.ResourceProperties.RepositoryArn) default_branch_name = determine_default_branch_name(repo_name) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/handler.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/handler.py index 05ef5bec9..1f91a49cc 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/handler.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/handler.py @@ -15,14 +15,17 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get("PhysicalResourceId", "NOT_YET_CREATED"), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( + "PhysicalResourceId", + "NOT_YET_CREATED", + ), + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/requirements.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/requirements.txt index 8893fb11e..b2109c785 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/requirements.txt +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/determine_default_branch/requirements.txt @@ -1,2 +1,2 @@ -boto3==1.26.133 +boto3==1.28.8 cfn-custom-resource~=1.0.1 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/iam_cfn_deploy_role_policy.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/iam_cfn_deploy_role_policy.py index 3049e02bf..71b00df30 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/iam_cfn_deploy_role_policy.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/iam_cfn_deploy_role_policy.py @@ -54,7 +54,7 @@ def _get_statement(self, statement_id): return s3_statements[0] if len(s3_statements) > 1: - raise Exception( + raise AssertionError( f'Found multiple {statement_id} statements in ' f'Role {self.role_name} Policy {self.policy_name}.' ) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/handler.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/handler.py index 19fe9a2b6..e6c08969a 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/handler.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/handler.py @@ -4,8 +4,8 @@ """ try: - from initial_commit import lambda_handler # pylint: disable=unused-import -except Exception as err: # pylint: disable=broad-except + from initial_commit import lambda_handler # pylint: disable=unused-import +except Exception as err: # pylint: disable=broad-except import os import logging from urllib.request import Request, urlopen @@ -15,17 +15,17 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get( + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( "PhysicalResourceId", "NOT_YET_CREATED", ), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/initial_commit.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/initial_commit.py index c5ea4329b..4ceaa6adb 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/initial_commit.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/initial_commit.py @@ -19,6 +19,8 @@ delete, ) +# pylint: disable=invalid-name + PhysicalResourceId = str Data = Mapping[str, str] @@ -51,6 +53,7 @@ @dataclass class CustomResourceProperties: + # pylint: disable=too-many-instance-attributes ServiceToken: str RepositoryArn: str DirectoryName: str @@ -247,6 +250,7 @@ def generate_commits(event, repo_name, directory, parent_commit_id=None): Returns: str[]: The commit ids of the commits that were created. """ + # pylint: disable=too-many-locals directory_path = HERE / directory version = event.ResourceProperties.Version default_branch_name = event.ResourceProperties.DefaultBranchName diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/requirements.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/requirements.txt index 9aa75eb19..279e145cf 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/requirements.txt +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/initial_commit/requirements.txt @@ -1,4 +1,4 @@ Jinja2==3.1.2 -boto3==1.26.133 +boto3==1.28.8 cfn-custom-resource~=1.0.1 -markupsafe==2.1.1 +markupsafe==2.1.3 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/requirements.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/requirements.txt index 272e34c72..188d33645 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/requirements.txt +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/requirements.txt @@ -1,4 +1,4 @@ -pyyaml==5.4.1 +pyyaml~=6.0.1 schema==0.7.5 -tenacity==8.1.0 +tenacity==8.2.2 wrapt==1.14.1 # https://github.com/aws/aws-lambda-builders/issues/302 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py index 3346850a9..0a72ecafc 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/config.py @@ -22,6 +22,7 @@ class Config: """ Class used for modeling adfconfig and its properties. """ + # pylint: disable=too-many-instance-attributes def __init__(self, parameter_store=None, config_path=None): self.parameters_client = parameter_store or ParameterStore( diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py index d1fed23be..48668444d 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py @@ -195,6 +195,7 @@ def _store_extension_parameters(parameter_store, config): ) +# pylint: disable=too-many-locals def worker_thread( account_id, sts, @@ -268,7 +269,7 @@ def worker_thread( 'Unit within AWS Organizations.', account_id, ) - raise Exception from error + raise LookupError from error except GenericAccountConfigureError as generic_account_error: LOGGER.info(generic_account_error) @@ -303,9 +304,10 @@ def await_sfn_executions(sfn_client): "Account Management State Machine encountered a failed, " "timed out, or aborted execution. Please look into this problem " "before retrying the bootstrap pipeline. You can navigate to: " - f"https://{REGION_DEFAULT}.console.aws.amazon.com/states/home?" - f"region={REGION_DEFAULT}#/statemachines/" - f"view/{ACCOUNT_MANAGEMENT_STATE_MACHINE_ARN}" + "https://%s.console.aws.amazon.com/states/home?region=%s#/statemachines/view/%s", + REGION_DEFAULT, + REGION_DEFAULT, + ACCOUNT_MANAGEMENT_STATE_MACHINE_ARN, ) sys.exit(1) if _sfn_execution_exists_with( diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/organization_policy.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/organization_policy.py index 3790482d7..483eda0e6 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/organization_policy.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/organization_policy.py @@ -110,7 +110,8 @@ def clean_and_remove_policy_attachment( def apply( self, organizations, parameter_store, config - ): # pylint: disable=R0912, R0915 + ): + # pylint: disable=too-many-locals status = organizations.get_organization_info() if status.get("feature_set") != "ALL": LOGGER.info( @@ -165,7 +166,6 @@ def apply( "Parameter %s was not found in Parameter Store, continuing.", policy, ) - pass for _policy in _policies: path = ( diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/support.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/support.py index 7da40337d..ea025dd48 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/support.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/support.py @@ -17,11 +17,15 @@ class SupportLevel(Enum): ENTERPRISE = "enterprise" -class Support: # pylint: disable=R0904 +class Support: # pylint: disable=R0904 """ Class used for accessing AWS Support API """ - _config = Config(retries=dict(max_attempts=30)) + _config = Config( + retries={ + "max_attempts": 30, + }, + ) def __init__(self, role): self.client = role.client( @@ -126,7 +130,12 @@ def set_support_level_for_account( f'Invalid Support Tier Value: {desired_level.value}' ) - def _enable_support_for_account(self, account: Account, account_id, desired_level: SupportLevel): + def _enable_support_for_account( + self, + account: Account, + account_id, + desired_level: SupportLevel, + ): """ Raises a support ticket in the organization root account, enabling] support for the account specified by account_id. diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/vpc.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/vpc.py index cda3ae001..7e98775c1 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/vpc.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/vpc.py @@ -18,18 +18,18 @@ def vpc_cleanup(account_id, vpcid, role, region): ec2client = ec2.meta.client vpc = ec2.Vpc(vpcid) # Detach and delete all gateways associated with the VPC - for gw in vpc.internet_gateways.all(): - vpc.detach_internet_gateway(InternetGatewayId=gw.id) - gw.delete() + for gateway in vpc.internet_gateways.all(): + vpc.detach_internet_gateway(InternetGatewayId=gateway.id) + gateway.delete() # Route table associations - for rt in vpc.route_tables.all(): - for rta in rt.associations: - if not rta.main: - rta.delete() + for route_table in vpc.route_tables.all(): + for rt_association in route_table.associations: + if not rt_association.main: + rt_association.delete() # Security Group - for sg in vpc.security_groups.all(): - if sg.group_name != 'default': - sg.delete() + for security_group in vpc.security_groups.all(): + if security_group.group_name != 'default': + security_group.delete() # Network interfaces for subnet in vpc.subnets.all(): for interface in subnet.network_interfaces.all(): @@ -74,7 +74,7 @@ def delete_default_vpc(client, account_id, region, role): max_retry_seconds = + 2 sleep(2) if max_retry_seconds <= 0: - raise Exception( + raise StopIteration( "Could not describe VPCs within retry limit.", ) from error diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements-dev.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements-dev.txt new file mode 100644 index 000000000..4edac7e10 --- /dev/null +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements-dev.txt @@ -0,0 +1,3 @@ +mock~=5.1.0 +pylint~=2.17.4 +pytest~=7.4.0 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements.txt index 55e377813..13cbc5b7e 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements.txt +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements.txt @@ -1,15 +1,12 @@ # Install libs here that you might want in AWS CodeBuild (On the management # account) -astroid==2.11.7 -aws-sam-cli==1.83.0 -awscli==1.27.133 -boto3==1.26.133 -botocore==1.29.133 -mock~=5.0.1 -pip~=22.3.1 -pylint~=2.13.9 -pytest~=7.2.0 -pyyaml~=5.4 +astroid==2.15.6 +aws-sam-cli==1.93.0 +awscli==1.29.8 +boto3==1.28.8 +botocore==1.31.8 +pip~=23.2 +pyyaml~=6.0.1 six~=1.16.0 -tenacity==8.1.0 -urllib3~=1.26.14 +tenacity==8.2.2 +urllib3~=1.26.16 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/base_resolver.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/base_resolver.py index 5506dd0b6..f7fa54c26 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/base_resolver.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/base_resolver.py @@ -35,7 +35,6 @@ def resolve(self, lookup_str: str, random_filename: str) -> str: Returns: str: The value as looked up using the intrinsic function. """ - pass @abstractmethod def supports(self, lookup_str: str) -> bool: @@ -50,7 +49,6 @@ def supports(self, lookup_str: str) -> bool: bool: True if this resolver supports the lookup_str syntax. False if not. """ - pass @staticmethod def _is_optional(value: str) -> bool: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codebuild.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codebuild.py index 372637c5f..7c1ace2e3 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codebuild.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codebuild.py @@ -30,9 +30,8 @@ class CodeBuild(Construct): - # pylint: disable=no-value-for-parameter + # pylint: disable=no-value-for-parameter, too-many-locals - # pylint: disable=W0622 def __init__( self, scope: Construct, @@ -247,7 +246,7 @@ def _setup_vpc(self, default_provider, target=None): ) if vpc_id: if not subnet_ids: - raise Exception( + raise ValueError( "CodeBuild environment of " f"{self.pipeline_project.project_name} has a " f"VPC Id ({vpc_id}) set, but no subnets are configured. " @@ -283,7 +282,7 @@ def _setup_vpc(self, default_provider, target=None): }, ) elif subnet_ids or security_group_ids: - raise Exception( + raise ValueError( "CodeBuild environment of " f"{self.pipeline_project.project_name} requires a VPC Id when " "configured to connect to specific subnets." @@ -299,7 +298,7 @@ def _determine_stage_build_spec( filename = props.get('spec_filename') spec_inline = props.get('spec_inline', {}) if filename and spec_inline: - raise Exception( + raise AssertionError( "The spec_filename and spec_inline are both present " f"inside the {stage_name} stage definition of {codebuild_id}. " "Whereas only one of these two is allowed." @@ -353,7 +352,7 @@ def get_image_by_name(specific_image: str): return _codebuild.LinuxBuildImage.from_docker_registry( specific_image, ) - raise Exception( + raise ValueError( f"The CodeBuild image {specific_image} could not be found." ) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codepipeline.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codepipeline.py index 5c3ce293a..4e5775e72 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codepipeline.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_codepipeline.py @@ -46,6 +46,7 @@ def get_partition(region_name: str) -> str: ADF_DEPLOYMENT_PARTITION = get_partition(ADF_DEPLOYMENT_REGION) +# pylint: disable=too-many-instance-attributes class Action: _version = "1" @@ -196,7 +197,7 @@ def _generate_configuration(self): .get('repository', self.map_params['name']) ) if not default_source_props.get('codestar_connection_arn'): - raise Exception( + raise ValueError( "The CodeStar Connection Arn could not be resolved for " f"the {self.map_params['name']} pipeline. Please check " "whether the codestar_connection_path is setup correctly " @@ -502,7 +503,7 @@ def _generate_configuration(self): if output_artifact_format: props["OutputArtifactFormat"] = output_artifact_format return props - raise Exception(f"{self.provider} is not a valid provider") + raise ValueError(f"{self.provider} is not a valid provider") def _generate_codepipeline_access_role(self): # pylint: disable=R0911 account_id = ( @@ -563,7 +564,7 @@ def _generate_codepipeline_access_role(self): # pylint: disable=R0911 ) if self.provider == "Manual": return None - raise Exception(f'Invalid Provider {self.provider}') + raise ValueError(f'Invalid Provider {self.provider}') def generate(self): pipeline_role = self._generate_codepipeline_access_role() @@ -835,10 +836,12 @@ def import_required_arns(): def add_pipeline_trigger(self, trigger_type, trigger_config): if trigger_type not in self._accepted_triggers: LOGGER.error( - f"{trigger_type} is not currently supported. " - f"Supported values are: {self._accepted_triggers.keys()}" + "%s is not currently supported. " + "Supported values are: %s", + trigger_type, + ', '.join(self._accepted_triggers.keys()), ) - raise Exception( + raise ValueError( f"{trigger_type} is not currently supported as " "a pipeline trigger" ) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_events.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_events.py index e1ee4f1b2..d57ed3613 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_events.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_events.py @@ -23,7 +23,8 @@ class Events(Construct): - def __init__(self, scope: Construct, id: str, params: dict, **kwargs): # pylint: disable=W0622 + # pylint: disable=too-many-locals + def __init__(self, scope: Construct, id: str, params: dict, **kwargs): super().__init__(scope, id, **kwargs) # pylint: disable=no-value-for-parameter stack = Stack.of(self) @@ -48,7 +49,8 @@ def __init__(self, scope: Construct, id: str, params: dict, **kwargs): # pylint description=f'Triggers {name} on changes in source CodeCommit repository', event_pattern=_events.EventPattern( resources=[ - f'arn:{stack.partition}:codecommit:{ADF_DEPLOYMENT_REGION}:{account_id}:{repo_name}' + f'arn:{stack.partition}:codecommit:' + f'{ADF_DEPLOYMENT_REGION}:{account_id}:{repo_name}' ], source=["aws.codecommit"], detail_type=[ @@ -102,7 +104,8 @@ def __init__(self, scope: Construct, id: str, params: dict, **kwargs): # pylint _targets.SnsTopic( topic=_topic, message=_events.RuleTargetInput.from_text( - # Need to parse and get the pipeline: "$.detail.pipeline" state: "$.detail.state" + # Need to parse and get the pipeline: "$.detail.pipeline" + # state: "$.detail.state" f"The pipeline {_events.EventField.from_path('$.detail.pipeline')} " f"from account {_events.EventField.account} " f"has {_events.EventField.from_path('$.detail.state')} " diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_github.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_github.py index 88ca59538..23a10e14f 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_github.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_github.py @@ -46,14 +46,22 @@ def create_webhook_when_required(scope, pipeline, map_params): pipeline_version = pipeline.get_att('Version') branch_name = ( - map_params.get('default_providers', {}).get('source', {}).get('properties', {}).get('branch') + ( + map_params + .get('default_providers', {}) + .get('source', {}) + .get('properties', {}) + .get('branch') + ) or 'master' ) _codepipeline.CfnWebhook( scope, 'github_webhook', authentication_configuration=_codepipeline.CfnWebhook.WebhookAuthConfigurationProperty( - secret_token=map_params['name'] # We can't have a randomly generated string here as it could update and change its value frequently + # We can't have a randomly generated string here as it could + # update and change its value frequently + secret_token=map_params['name'] ), authentication="GITHUB_HMAC", target_pipeline=pipeline.ref, diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_notifications.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_notifications.py index 54d0d521a..849a352b6 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_notifications.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_constructs/adf_notifications.py @@ -36,7 +36,11 @@ def __init__( f'arn:{stack.partition}:lambda:{ADF_DEPLOYMENT_REGION}:' f'{ADF_DEPLOYMENT_ACCOUNT_ID}:function:SendSlackNotification' ) - kms_alias = _kms.Alias.from_alias_name(self, "KMSAlias", f"alias/codepipeline-{ADF_DEPLOYMENT_ACCOUNT_ID}") + kms_alias = _kms.Alias.from_alias_name( + self, + "KMSAlias", + f"alias/codepipeline-{ADF_DEPLOYMENT_ACCOUNT_ID}", + ) _topic = _sns.Topic(self, "PipelineTopic", master_key=kms_alias) _statement = _iam.PolicyStatement( actions=["sns:Publish"], diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_stacks/adf_default_pipeline.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_stacks/adf_default_pipeline.py index b63cd7048..e638c5c2b 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_stacks/adf_default_pipeline.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/cdk_stacks/adf_default_pipeline.py @@ -175,6 +175,7 @@ def _generate_build_stage_for_pipeline(scope, stack_input): def _generate_stages_with_targets_for_pipeline(scope, stack_input): + # pylint: disable=too-many-locals stages = [] for index, targets in enumerate( stack_input["pipeline_input"] diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/clean_pipelines.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/clean_pipelines.py index db3d16faa..90503c990 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/clean_pipelines.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/cdk/clean_pipelines.py @@ -54,7 +54,7 @@ def clean(parameter_store, deployment_map): for pipeline in deployment_map.map_contents["pipelines"] ] if name not in defined_pipelines: - LOGGER.info(f'Deleting {parameter.get("Name")}') + LOGGER.info('Deleting %s', parameter.get("Name")) parameter_store.delete_parameter(parameter.get("Name")) stacks_to_remove.append(name) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/requirements.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/requirements.txt index 95b26318a..571335443 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/requirements.txt +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/requirements.txt @@ -1,3 +1,3 @@ -boto3==1.26.133 -botocore==1.29.133 +boto3==1.28.8 +botocore==1.31.8 docopt~=0.6.2 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/retrieve_organization_accounts.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/retrieve_organization_accounts.py index f8c8db83b..7080131f3 100755 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/retrieve_organization_accounts.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/retrieve_organization_accounts.py @@ -112,7 +112,8 @@ def main(): The two options defined using the `-f` argument, specify that we are interested in the `Id` and the `Email` of the member accounts. All other details that would otherwise be returned by the - [Organizations: ListAccounts](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/organizations.html#Organizations.Client.list_accounts) + [Organizations: ListAccounts]( + https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/organizations.html#Organizations.Client.list_accounts) API will be ignored. --- diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/sync_to_s3.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/sync_to_s3.py index 4054a7c85..750711158 100755 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/sync_to_s3.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/sync_to_s3.py @@ -535,6 +535,7 @@ def _get_upload_reason( return "metadata changed" +# pylint: disable=too-many-locals def upload_changed_files( s3_client: any, s3_bucket: str, diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudformation.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudformation.py index a71e00bda..fd3f3f3fc 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudformation.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudformation.py @@ -18,9 +18,9 @@ LOGGER = configure_logger(__name__) STACK_TERMINATION_PROTECTION = os.environ.get('TERMINATION_PROTECTION', False) CFN_CONFIG = Config( - retries=dict( - max_attempts=10 - ) + retries={ + "max_attempts": 10, + }, ) # A stack name can contain only alphanumeric characters (case sensitive) # and hyphens. @@ -116,6 +116,7 @@ class WaitException(Exception): class CloudFormation(StackProperties): + # pylint: disable=too-many-arguments def __init__( self, region, @@ -513,7 +514,7 @@ def get_stack_output(self, value): ) return [item.get('OutputValue') for item in response.get('Stacks') [0].get('Outputs') if item.get('OutputKey') == value][0] - except BaseException: + except BaseException: # pylint: disable=broad-exception-caught LOGGER.warning( "%s in %s - Attempted to get stack output from %s " "but it failed.", diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudwatch.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudwatch.py index ac05e64eb..57a228e63 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudwatch.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/cloudwatch.py @@ -9,13 +9,14 @@ class ADFMetrics: def __init__(self, client: boto3.client, service, namespace="ADF") -> None: """ Client: Any Boto3 CloudWatch client - Service: The name of the Service e.g PipelineManagement/Repository or AccountManagement/EnableSupport - namespace: Defaults to ADF + Service: The name of the Service e.g PipelineManagement/Repository + or AccountManagement/EnableSupport namespace. + Defaults to ADF. """ - self.cw = client + self.cw_client = client self.namespace = f"{namespace}/{service}" def put_metric_data(self, metric_data): if not isinstance(metric_data, list): metric_data = [metric_data] - self.cw.put_metric_data(Namespace=self.namespace, MetricData=metric_data) + self.cw_client.put_metric_data(Namespace=self.namespace, MetricData=metric_data) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/deployment_map.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/deployment_map.py index 16bb4cd5c..4bf69ef74 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/deployment_map.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/deployment_map.py @@ -89,7 +89,8 @@ def _get_all(self): if os.path.isdir(self.map_dir_path): self._process_dir(self.map_dir_path) self.determine_extend_map( - self._read() # Calling with default no args to get deployment_map.yml in root if it exists + # Calling with default no args to get deployment_map.yml in root if it exists + self._read() ) if not self.map_contents['pipelines']: LOGGER.error( @@ -103,7 +104,7 @@ def _get_all(self): def _process_dir(self, path): files = [os.path.join(path, f) for f in os.listdir(path)] for filename in files: - LOGGER.info(f"Processing {filename} in path {path}") + LOGGER.info("Processing %s in path %s", filename, path) if os.path.isdir(filename): self._process_dir(filename) elif filename.endswith(".yml") and filename != "example-deployment_map.yml": @@ -111,4 +112,7 @@ def _process_dir(self, path): self._read(filename) ) else: - LOGGER.warning("%s is not a directory and doesn't hold the .yml suffix", filename) + LOGGER.warning( + "%s is not a directory and doesn't hold the .yml suffix", + filename, + ) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/errors.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/errors.py index d04ce33d1..5c6b91dad 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/errors.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/errors.py @@ -9,22 +9,16 @@ class Error(Exception): """Base class for exceptions in this module.""" - pass - class RetryError(Exception): """Retry Error used for Step Functions logic""" - pass - class ParameterNotFoundError(Exception): """ Parameter not found in Parameter Store """ - pass - class InvalidConfigError(Exception): """ @@ -38,8 +32,6 @@ class GenericAccountConfigureError(Exception): Generic Account cannot be setup since no base stack is present """ - pass - class AccountCreationNotFinishedError(Exception): """ @@ -56,28 +48,20 @@ class RootOUIDError(Exception): and a describe call is attempted again the root of the org. """ - pass - class InvalidTemplateError(Exception): """ Raised when a CloudFormation template fails the Validate Template call """ - pass - class InvalidDeploymentMapError(Exception): """ Raised when a Deployment Map is invalid """ - pass - class NoAccountsFoundError(Exception): """ Raised when there are no Accounts found a specific OU defined in the Deployment Map """ - - pass diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/organizations.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/organizations.py index 3cea74ed4..72ae8c8b9 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/organizations.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/organizations.py @@ -26,7 +26,11 @@ class Organizations: # pylint: disable=R0904 Class used for modeling Organizations """ - _config = Config(retries=dict(max_attempts=30)) + _config = Config( + retries={ + "max_attempts": 30, + }, + ) def __init__(self, role, account_id=None): self.client = role.client( @@ -90,7 +94,7 @@ def trim_policy_path(policy): @staticmethod def is_ou_id(ou_id): - return ou_id[0] in ['r','o'] + return ou_id[0] in ['r', 'o'] def get_organization_map(self, org_structure, counter=0): for name, ou_id in org_structure.copy().items(): @@ -132,7 +136,8 @@ def get_organization_map(self, org_structure, counter=0): ) org_structure[trimmed_path] = account_id counter = counter + 1 - # Counter is greater than 5 here is the conditional as organizations cannot have more than 5 levels of nested OUs + 1 accounts "level" + # Counter is greater than 5 here is the conditional as organizations + # cannot have more than 5 levels of nested OUs + 1 accounts "level" return ( org_structure if counter > 5 else self.get_organization_map(org_structure, counter) @@ -344,18 +349,20 @@ def get_ou_root_id(self): return self.client.list_roots().get('Roots')[0].get('Id') def dir_to_ou(self, path): - p = path.split('/')[1:] + nested_dir_paths = path.split('/')[1:] ou_id = self.get_ou_root_id() - while p: + while nested_dir_paths: for ou in self.get_child_ous(ou_id): - if ou['Name'] == p[0]: - p.pop(0) + if ou['Name'] == nested_dir_paths[0]: + nested_dir_paths.pop(0) ou_id = ou['Id'] break else: - raise Exception(f"Path {path} failed to return a child OU at '{p[0]}'") - else: # pylint: disable=W0120 + raise ValueError( + f"Path {path} failed to return a child OU at '{nested_dir_paths[0]}'", + ) + else: # pylint: disable=W0120 return self.get_accounts_for_parent(ou_id) def build_account_path(self, ou_id, account_path, cache): @@ -395,7 +402,12 @@ def get_account_ids_for_tags(self, tags): values = [value] tag_filter.append({'Key': key, 'Values': values}) account_ids = [] - for resource in paginator(self.tags_client.get_resources, TagFilters=tag_filter, ResourceTypeFilters=['organizations']): + paginated_resources = paginator( + self.tags_client.get_resources, + TagFilters=tag_filter, + ResourceTypeFilters=['organizations'], + ) + for resource in paginated_resources: arn = resource['ResourceARN'] account_id = arn.split('/')[::-1][0] account_ids.append(account_id) @@ -404,7 +416,10 @@ def get_account_ids_for_tags(self, tags): def list_organizational_units_for_parent(self, parent_ou): organizational_units = [ ou - for org_units in self.client.get_paginator("list_organizational_units_for_parent").paginate(ParentId=parent_ou) + for org_units in ( + self.client.get_paginator("list_organizational_units_for_parent") + .paginate(ParentId=parent_ou) + ) for ou in org_units['OrganizationalUnits'] ] return organizational_units @@ -448,7 +463,9 @@ def get_ou_id(self, ou_path, parent_ou_id=None): hierarchy_index += 1 break else: - raise ValueError(f'Could not find ou with name {ou_hierarchy} in OU list {org_units}.') + raise ValueError( + f'Could not find ou with name {ou_hierarchy} in OU list {org_units}.', + ) return parent_ou_id diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/parameter_store.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/parameter_store.py index bb9f0ceb8..b20ee5f57 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/parameter_store.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/parameter_store.py @@ -12,9 +12,9 @@ LOGGER = configure_logger(__name__) PARAMETER_DESCRIPTION = 'DO NOT EDIT - Used by The AWS Deployment Framework' SSM_CONFIG = Config( - retries=dict( - max_attempts=10 - ) + retries={ + "max_attempts": 10, + }, ) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/s3.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/s3.py index 550311a77..0dc264739 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/s3.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/s3.py @@ -73,7 +73,7 @@ def build_pathing_style(self, style, key): if style == 'virtual-hosted': return f"https://{self.bucket}.{s3_region_name}.amazonaws.com/{key}" - raise Exception( + raise ValueError( f"Unknown upload style syntax: {style}. " "Valid options include: s3-uri, path, or " "virtual-hosted." @@ -199,13 +199,18 @@ def fetch_s3_url(self, key): # searching if len(key_level_up) == 1: LOGGER.debug( - 'Nothing could be found for %s when traversing the bucket', key) + 'Nothing could be found for %s when traversing the bucket', + key, + ) return [] LOGGER.debug( - 'Unable to find the specified Key: %s - looking one level up', key) - # remove the key name in which we did not find the file we wanted this attempt - # (-1 will be json/yml file, -2 will be the key prefix) which we want to leave + 'Unable to find the specified Key: %s - looking one level up', + key, + ) + # remove the key name in which we did not find the file we wanted + # this attempt (-1 will be json/yml file, -2 will be the key + # prefix) which we want to leave del key_level_up[-2] # Join it back together, and recursive call the function with the diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/stepfunctions.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/stepfunctions.py index 8718ab056..5417864b1 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/stepfunctions.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/stepfunctions.py @@ -52,14 +52,16 @@ def execute_statemachine(self): def _start_statemachine(self): """ - Executes the Update Cross Account IAM Step Function in the Deployment Account + Executes the Update Cross Account IAM Step Function in the + Deployment Account """ partition = get_partition(self.deployment_account_region) self.execution_arn = self.client.start_execution( stateMachineArn=( f"arn:{partition}:states:{self.deployment_account_region}:" - f"{self.deployment_account_id}:stateMachine:EnableCrossAccountAccess" + f"{self.deployment_account_id}:stateMachine:" + "EnableCrossAccountAccess" ), input=json.dumps({ "deployment_account_region": self.deployment_account_region, @@ -107,7 +109,8 @@ def _wait_state_machine_execution(self): sleep(10) # Wait for 10 seconds and check the status again if self.execution_status in ('FAILED', 'ABORTED', 'TIMED_OUT'): - raise Exception( - f'State Machine on Deployment account {self.deployment_account_id} ' - f'has status: {self.execution_status}, see logs' + raise AssertionError( + "State Machine on Deployment account" + f"{self.deployment_account_id} has " + f"status: {self.execution_status}, see logs" ) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements-dev.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements-dev.txt new file mode 100644 index 000000000..c88fd67fb --- /dev/null +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements-dev.txt @@ -0,0 +1,2 @@ +mock~=5.1.0 +pytest~=7.4.0 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements.txt b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements.txt index 2efbdd798..018ce260e 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements.txt +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements.txt @@ -1,14 +1,12 @@ # Install libs here that you might want in AWS CodeBuild -aws-cdk-lib==2.79.1 +aws-cdk-lib~=2.88.0 constructs>=10.0.0,<11.0.0 -aws-sam-cli==1.83.0 -awscli==1.27.133 -boto3==1.26.133 -botocore==1.29.133 -mock~=5.0.1 -pytest~=7.2.0 -pyyaml~=5.4 +aws-sam-cli==1.93.0 +awscli==1.29.8 +boto3==1.28.8 +botocore==1.31.8 +pyyaml~=6.0.1 schema~=0.7.5 -tenacity==8.1.0 -typing-extensions~=4.4.0 -urllib3~=1.26.14 +tenacity==8.2.2 +typing-extensions~=4.7.1 +urllib3~=1.26.16 diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_param_store.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_param_store.py index 3e9a171b9..432c93bb6 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_param_store.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_param_store.py @@ -73,7 +73,6 @@ def resolve(self, lookup_str: str, random_filename: str) -> str: # To enable an easy interface that could do lookups # whether a specific lookup string is supported or not it # should be instance based. Disabling: no-self-use warning - # pylint: disable=R0201 def supports(self, lookup_str: str) -> bool: """ Check if this resolver supports the lookup_str syntax. diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_stack_output.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_stack_output.py index fd6f7a192..5ceefa4f3 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_stack_output.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_stack_output.py @@ -98,7 +98,7 @@ def resolve(self, lookup_str: str, random_filename: str) -> str: LOGGER.info("Stack output value is %s", stack_output) self.cache.add(lookup_str, stack_output) elif not optional: - raise Exception( + raise LookupError( f"No Stack Output found on {account_id} in {region} " f"with stack name {stack_name} and " f"output key {output_key}" @@ -108,7 +108,6 @@ def resolve(self, lookup_str: str, random_filename: str) -> str: # To enable an easy interface that could do lookups # whether a specific lookup string is supported or not it # should be instance based. Disabling: no-self-use warning - # pylint: disable=R0201 def supports(self, lookup_str: str) -> bool: """ Check if this resolver supports the lookup_str syntax. diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_upload.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_upload.py index 357c3598f..e94e23d8b 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_upload.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/resolver_upload.py @@ -57,7 +57,7 @@ def resolve(self, lookup_str: str, random_filename: str) -> str: item in lookup_str for item in S3.supported_path_styles() ): - raise Exception( + raise ValueError( 'When uploading to S3 you need to specify a path style' 'to use for the returned value to be used. ' f'Supported path styles include: {S3.supported_path_styles()}' @@ -83,7 +83,6 @@ def resolve(self, lookup_str: str, random_filename: str) -> str: # To enable an easy interface that could do lookups # whether a specific lookup string is supported or not it # should be instance based. Disabling: no-self-use warning - # pylint: disable=R0201 def supports(self, lookup_str: str) -> bool: """ Check if this resolver supports the lookup_str syntax. diff --git a/src/lambda_codebase/initial_commit/handler.py b/src/lambda_codebase/initial_commit/handler.py index 4df50ae57..5e639af03 100644 --- a/src/lambda_codebase/initial_commit/handler.py +++ b/src/lambda_codebase/initial_commit/handler.py @@ -4,8 +4,8 @@ """ try: - from initial_commit import lambda_handler # pylint: disable=unused-import -except Exception as err: # pylint: disable=broad-except + from initial_commit import lambda_handler # pylint: disable=unused-import +except Exception as err: # pylint: disable=broad-except import os import logging from urllib.request import Request, urlopen @@ -15,17 +15,17 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get( + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( "PhysicalResourceId", "NOT_YET_CREATED", ), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/initial_commit/initial_commit.py b/src/lambda_codebase/initial_commit/initial_commit.py index 85ba5592e..994a890bb 100644 --- a/src/lambda_codebase/initial_commit/initial_commit.py +++ b/src/lambda_codebase/initial_commit/initial_commit.py @@ -19,6 +19,8 @@ delete, ) +# pylint: disable=invalid-name + PhysicalResourceId = str Data = Mapping[str, str] @@ -66,6 +68,7 @@ @dataclass class CustomResourceProperties: + # pylint: disable=too-many-instance-attributes ServiceToken: str RepositoryArn: str DirectoryName: str @@ -266,6 +269,7 @@ def generate_commits(event, repo_name, directory, parent_commit_id=None): Returns: str[]: The commit ids of the commits that were created. """ + # pylint: disable=too-many-locals directory_path = HERE / directory version = event.ResourceProperties.Version default_branch_name = event.ResourceProperties.DefaultBranchName diff --git a/src/lambda_codebase/initial_commit/requirements.txt b/src/lambda_codebase/initial_commit/requirements.txt index 9aa75eb19..279e145cf 100644 --- a/src/lambda_codebase/initial_commit/requirements.txt +++ b/src/lambda_codebase/initial_commit/requirements.txt @@ -1,4 +1,4 @@ Jinja2==3.1.2 -boto3==1.26.133 +boto3==1.28.8 cfn-custom-resource~=1.0.1 -markupsafe==2.1.1 +markupsafe==2.1.3 diff --git a/src/lambda_codebase/moved_to_root.py b/src/lambda_codebase/moved_to_root.py index b6642817c..d0edc1e98 100644 --- a/src/lambda_codebase/moved_to_root.py +++ b/src/lambda_codebase/moved_to_root.py @@ -62,7 +62,7 @@ def remove_base(account_id, regions, role, event): threads = [] for region in list(set([event.get('deployment_account_region')] + regions)): - t = PropagatingThread( + thread = PropagatingThread( target=worker_thread, args=( sts, @@ -72,8 +72,8 @@ def remove_base(account_id, regions, role, event): event, ), ) - t.start() - threads.append(t) + thread.start() + threads.append(thread) for thread in threads: thread.join() diff --git a/src/lambda_codebase/organization/handler.py b/src/lambda_codebase/organization/handler.py index 69a2443a0..a4e96fbb3 100644 --- a/src/lambda_codebase/organization/handler.py +++ b/src/lambda_codebase/organization/handler.py @@ -2,12 +2,13 @@ # SPDX-License-Identifier: MIT-0 """ -The Organization Handler that is called when ADF is installed to create the organization if required +The Organization Handler that is called when ADF is installed to create the +organization if required """ try: - from main import lambda_handler # pylint: disable=unused-import -except Exception as err: # pylint: disable=broad-except + from main import lambda_handler # pylint: disable=unused-import +except Exception as err: # pylint: disable=broad-except import os import logging from urllib.request import Request, urlopen @@ -17,17 +18,20 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get( + """ + Handler for custom resource + """ + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( "PhysicalResourceId", "NOT_YET_CREATED", ), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/organization/main.py b/src/lambda_codebase/organization/main.py index 74045ab9b..cdc510212 100644 --- a/src/lambda_codebase/organization/main.py +++ b/src/lambda_codebase/organization/main.py @@ -13,7 +13,6 @@ import json import boto3 from cfn_custom_resource import ( # pylint: disable=unused-import - lambda_handler, create, update, delete, @@ -34,23 +33,30 @@ class InvalidPhysicalResourceId(Exception): - pass + """ + Invalid Physical Resource Id specified + """ @dataclass class PhysicalResource: + """ + Custom Resource Physical Resource data class + """ organization_id: str created: bool organization_root_id: str @classmethod def from_json(cls, json_string: PhysicalResourceId) -> "PhysicalResource": + """Convert from JSON to data class""" try: return cls(**json.loads(json_string)) except json.JSONDecodeError as err: raise InvalidPhysicalResourceId from err def as_cfn_response(self) -> Tuple[PhysicalResourceId, Data]: + """Convert to CloudFormation response""" physical_resource_id = json.dumps(asdict(self)) data = { "OrganizationId": self.organization_id, @@ -69,7 +75,7 @@ def create_(_event: Mapping[str, Any], _context: Any) -> CloudFormationResponse: region = os.getenv('AWS_REGION') if region not in approved_regions: - raise Exception( + raise ValueError( "Deployment of ADF is only available via the us-east-1 " "and us-gov-west-1 regions." ) @@ -125,7 +131,7 @@ def ensure_organization() -> Tuple[OrganizationId, Created]: return organization_id, True if describe_organization["Organization"]["FeatureSet"] != "ALL": - raise Exception( + raise EnvironmentError( "Existing organization is only set up for CONSOLIDATED_BILLING, " "but ADF needs ALL features" ) @@ -146,6 +152,6 @@ def get_organization_root_id() -> str: organization_root_id = roots["Roots"][0]["Id"] LOGGER.info("ORG root id is: %s", organization_root_id) return cast(str, organization_root_id) - if not "NextToken" in roots: - raise Exception("Unable to find ORG root id") + if "NextToken" not in roots: + raise EnvironmentError("Unable to find ORG root id") params["next_token"] = roots["NextToken"] diff --git a/src/lambda_codebase/organization_unit/handler.py b/src/lambda_codebase/organization_unit/handler.py index b36371450..761674640 100644 --- a/src/lambda_codebase/organization_unit/handler.py +++ b/src/lambda_codebase/organization_unit/handler.py @@ -7,8 +7,8 @@ """ try: - from main import lambda_handler # pylint: disable=unused-import -except Exception as err: # pylint: disable=broad-except + from main import lambda_handler # pylint: disable=unused-import +except Exception as err: # pylint: disable=broad-except import os import logging from urllib.request import Request, urlopen @@ -18,17 +18,17 @@ LOGGER.setLevel(os.environ.get("ADF_LOG_LEVEL", logging.INFO)) def lambda_handler(event, _context, prior_error=err): - payload = dict( - LogicalResourceId=event["LogicalResourceId"], - PhysicalResourceId=event.get( + payload = { + "LogicalResourceId": event["LogicalResourceId"], + "PhysicalResourceId": event.get( "PhysicalResourceId", "NOT_YET_CREATED", ), - Status="FAILED", - RequestId=event["RequestId"], - StackId=event["StackId"], - Reason=str(prior_error), - ) + "Status": "FAILED", + "RequestId": event["RequestId"], + "StackId": event["StackId"], + "Reason": str(prior_error), + } with urlopen( Request( event["ResponseURL"], diff --git a/src/lambda_codebase/organization_unit/main.py b/src/lambda_codebase/organization_unit/main.py index 4de6d84a2..779825e1b 100644 --- a/src/lambda_codebase/organization_unit/main.py +++ b/src/lambda_codebase/organization_unit/main.py @@ -13,7 +13,6 @@ import time import boto3 from cfn_custom_resource import ( # pylint: disable=unused-import - lambda_handler, create, update, delete, @@ -114,7 +113,6 @@ def ensure_org_unit(parent_id: str, org_unit_name: str) -> Tuple[OrgUnitId, Crea return org_unit_id, True except ORGANIZATION_CLIENT.exceptions.DuplicateOrganizationalUnitException: LOGGER.info("deployment OU already exists") - pass except ORGANIZATION_CLIENT.exceptions.ConcurrentModificationException as err: LOGGER.info(err) time.sleep(10) @@ -122,7 +120,9 @@ def ensure_org_unit(parent_id: str, org_unit_name: str) -> Tuple[OrgUnitId, Crea params: dict = {"ParentId": parent_id} while True: - org_units = ORGANIZATION_CLIENT.list_organizational_units_for_parent(**params) + org_units = ORGANIZATION_CLIENT.list_organizational_units_for_parent( + **params, + ) for org_unit in filter( lambda ou: ou["Name"] == org_unit_name, org_units["OrganizationalUnits"], @@ -130,6 +130,6 @@ def ensure_org_unit(parent_id: str, org_unit_name: str) -> Tuple[OrgUnitId, Crea org_unit_id = org_unit["Id"] LOGGER.info("OU already exists: %s", org_unit_id) return org_unit_id, False - if not "NextToken" in org_units: - raise Exception("Unable to find OU") + if "NextToken" not in org_units: + raise ValueError("Unable to find OU") params["NextToken"] = org_units["NextToken"] diff --git a/src/lambda_codebase/requirements.txt b/src/lambda_codebase/requirements.txt index ddd53b90c..364b7e83c 100644 --- a/src/lambda_codebase/requirements.txt +++ b/src/lambda_codebase/requirements.txt @@ -1 +1 @@ -tenacity==8.1.0 +tenacity==8.2.2 diff --git a/src/lambda_codebase/wait_until_complete.py b/src/lambda_codebase/wait_until_complete.py index 317ab2211..b48381262 100644 --- a/src/lambda_codebase/wait_until_complete.py +++ b/src/lambda_codebase/wait_until_complete.py @@ -99,7 +99,7 @@ def lambda_handler(event, _): 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE', ): - raise Exception( + raise AssertionError( f"Account Bootstrap Failed - Account: {account_id} " f"Region: {region} Status: {status}" ) diff --git a/src/template.yml b/src/template.yml index bfbe18fbd..c1658f207 100644 --- a/src/template.yml +++ b/src/template.yml @@ -1301,7 +1301,7 @@ Resources: python: 3.11 pre_build: commands: - - pip install -r adf-build/requirements.txt -r adf-build/shared/helpers/requirements.txt --quiet + - pip install -r adf-build/requirements.txt -r adf-build/requirements-dev.txt -r adf-build/shared/helpers/requirements.txt --quiet - pytest -vvv build: commands: diff --git a/tox.ini b/tox.ini index 12af38e38..22dd1bfb1 100644 --- a/tox.ini +++ b/tox.ini @@ -30,6 +30,7 @@ allowlist_externals = python deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/requirements-dev.txt -r{toxinidir}/src/lambda_codebase/account/requirements.txt -r{toxinidir}/src/lambda_codebase/account_processing/requirements.txt -r{toxinidir}/src/lambda_codebase/cross_region_bucket/requirements.txt @@ -38,8 +39,10 @@ deps = -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/requirements.txt -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/requirements.txt -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements.txt + -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/requirements-dev.txt -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/requirements.txt -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements.txt + -r{toxinidir}/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/requirements-dev.txt -r{toxinidir}/src/lambda_codebase/initial_commit/requirements.txt -r{toxinidir}/src/lambda_codebase/organization/requirements.txt -r{toxinidir}/src/lambda_codebase/organization_unit/requirements.txt