diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed9355e80..d0a95dad7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ repos: - repo: https://github.com/ambv/black - rev: stable + rev: 24.8.0 hooks: - id: black - entry: black -l 79 src/api-engine src/agent/kubernetes-agent - language_version: python3.7 + entry: black -l 79 + language_version: python3.8 diff --git a/build_image/docker/cello-hlf/scripts/notifier.py b/build_image/docker/cello-hlf/scripts/notifier.py index 786b6baa8..fb07f0edd 100644 --- a/build_image/docker/cello-hlf/scripts/notifier.py +++ b/build_image/docker/cello-hlf/scripts/notifier.py @@ -1,39 +1,50 @@ import pyinotify wm = pyinotify.WatchManager() # Watch Manager -mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MODIFY | pyinotify.IN_MOVED_FROM | pyinotify.IN_MOVED_TO | pyinotify.IN_MOVE_SELF | pyinotify.IN_DELETE_SELF # watched events +mask = ( + pyinotify.IN_DELETE + | pyinotify.IN_CREATE + | pyinotify.IN_MODIFY + | pyinotify.IN_MOVED_FROM + | pyinotify.IN_MOVED_TO + | pyinotify.IN_MOVE_SELF + | pyinotify.IN_DELETE_SELF +) # watched events + class EventHandler(pyinotify.ProcessEvent): def process_IN_CREATE(self, event): - print "Creating:", event.pathname + print("Creating:", event.pathname) def process_IN_DELETE(self, event): - print "Removing:", event.pathname + print("Removing:", event.pathname) def process_IN_MODIFY(self, event): - print "Modifying:", event.pathname + print("Modifying:", event.pathname) def process_IN_MOVED_FROM(self, event): - print "Moved From:", event.pathname + print("Moved From:", event.pathname) def process_IN_MOVED_TO(self, event): - print "Moved To:", event.pathname + print("Moved To:", event.pathname) def process_IN_MOVE_SELF(self, event): - print "Moving Self:", event.pathname + print("Moving Self:", event.pathname) def process_IN_DELETE_SELF(self, event): - print "Deleting Self:", event.pathname + print("Deleting Self:", event.pathname) + handler = EventHandler() notifier = pyinotify.Notifier(wm, handler) # watch Hyperledger and HOME from os.path import expanduser + home = expanduser("~") -dirs = ['/etc/hyperledger/', '/var/hyperledger/', home] -for d in dirs: - print "Add watcher to "+d - wdd = wm.add_watch(d, mask, rec=True, auto_add=True) +dirs = ["/etc/hyperledger/", "/var/hyperledger/", home] +for dir in dirs: + print("Add watcher to", dir) + wdd = wm.add_watch(dir, mask, rec=True, auto_add=True) notifier.loop() diff --git a/kconfig-lib/kconfiglib.py b/kconfig-lib/kconfiglib.py index 4bb7eda0a..10dc1539c 100644 --- a/kconfig-lib/kconfiglib.py +++ b/kconfig-lib/kconfiglib.py @@ -985,7 +985,9 @@ def _init(self, filename, warn, warn_to_stderr, encoding): self.config_prefix = os.getenv("CONFIG_", "CONFIG_") # Regular expressions for parsing .config files self._set_match = _re_match(self.config_prefix + r"([^=]+)=(.*)") - self._unset_match = _re_match(r"# {}([^ ]+) is not set".format(self.config_prefix)) + self._unset_match = _re_match( + r"# {}([^ ]+) is not set".format(self.config_prefix) + ) self.config_header = os.getenv("KCONFIG_CONFIG_HEADER", "") self.header_header = os.getenv("KCONFIG_AUTOHEADER_HEADER", "") @@ -1112,7 +1114,10 @@ def _init(self, filename, warn, warn_to_stderr, encoding): # KCONFIG_STRICT is an older alias for KCONFIG_WARN_UNDEF, supported # for backwards compatibility - if os.getenv("KCONFIG_WARN_UNDEF") == "y" or os.getenv("KCONFIG_STRICT") == "y": + if ( + os.getenv("KCONFIG_WARN_UNDEF") == "y" + or os.getenv("KCONFIG_STRICT") == "y" + ): self._check_undef_syms() @@ -1220,12 +1225,18 @@ def load_config(self, filename=None, replace=True, verbose=None): msg = None if filename is None: filename = standard_config_filename() - if not exists(filename) and not exists(join(self.srctree, filename)): + if not exists(filename) and not exists( + join(self.srctree, filename) + ): defconfig = self.defconfig_filename if defconfig is None: - return "Using default symbol values (no '{}')".format(filename) + return "Using default symbol values (no '{}')".format( + filename + ) - msg = " default configuration '{}' (no '{}')".format(defconfig, filename) + msg = " default configuration '{}' (no '{}')".format( + defconfig, filename + ) filename = defconfig if not msg: @@ -1292,7 +1303,9 @@ def _load_config(self, filename, replace): self._warn( "'{}' is not a valid value for the {} " "symbol {}. Assignment ignored.".format( - val, TYPE_TO_STR[sym.orig_type], sym.name_and_loc + val, + TYPE_TO_STR[sym.orig_type], + sym.name_and_loc, ), filename, linenr, @@ -1307,10 +1320,14 @@ def _load_config(self, filename, replace): # to the choice symbols prev_mode = sym.choice.user_value - if prev_mode is not None and TRI_TO_STR[prev_mode] != val: + if ( + prev_mode is not None + and TRI_TO_STR[prev_mode] != val + ): self._warn( - "both m and y assigned to symbols " "within the same choice", + "both m and y assigned to symbols " + "within the same choice", filename, linenr, ) @@ -1323,7 +1340,9 @@ def _load_config(self, filename, replace): if not match: self._warn( "malformed string literal in " - "assignment to {}. Assignment ignored.".format(sym.name_and_loc), + "assignment to {}. Assignment ignored.".format( + sym.name_and_loc + ), filename, linenr, ) @@ -1340,7 +1359,9 @@ def _load_config(self, filename, replace): # rstrip()'d, so blank lines show up as "" here. if line and not line.lstrip().startswith("#"): self._warn( - "ignoring malformed line '{}'".format(line), filename, linenr + "ignoring malformed line '{}'".format(line), + filename, + linenr, ) continue @@ -1381,7 +1402,9 @@ def _undef_assign(self, name, val, filename, linenr): self.missing_syms.append((name, val)) if self.warn_assign_undef: self._warn( - "attempt to assign the value '{}' to the undefined symbol {}".format(val, name), + "attempt to assign the value '{}' to the undefined symbol {}".format( + val, name + ), filename, linenr, ) @@ -1463,7 +1486,9 @@ def write_autoconf(self, filename=None, header=None): in tools, which can do e.g. print(kconf.write_autoconf()). """ if filename is None: - filename = os.getenv("KCONFIG_AUTOHEADER", "include/generated/autoconf.h") + filename = os.getenv( + "KCONFIG_AUTOHEADER", "include/generated/autoconf.h" + ) if self._write_if_changed(filename, self._autoconf_contents(header)): return "Kconfig header saved to '{}'".format(filename) @@ -1492,22 +1517,38 @@ def _autoconf_contents(self, header): if sym.orig_type in _BOOL_TRISTATE: if val == "y": - add("#define {}{} 1\n".format(self.config_prefix, sym.name)) + add( + "#define {}{} 1\n".format(self.config_prefix, sym.name) + ) elif val == "m": - add("#define {}{}_MODULE 1\n".format(self.config_prefix, sym.name)) + add( + "#define {}{}_MODULE 1\n".format( + self.config_prefix, sym.name + ) + ) elif sym.orig_type is STRING: - add('#define {}{} "{}"\n'.format(self.config_prefix, sym.name, escape(val))) + add( + '#define {}{} "{}"\n'.format( + self.config_prefix, sym.name, escape(val) + ) + ) else: # sym.orig_type in _INT_HEX: if sym.orig_type is HEX and not val.startswith(("0x", "0X")): val = "0x" + val - add("#define {}{} {}\n".format(self.config_prefix, sym.name, val)) + add( + "#define {}{} {}\n".format( + self.config_prefix, sym.name, val + ) + ) return "".join(chunks) - def write_config(self, filename=None, header=None, save_old=True, verbose=None): + def write_config( + self, filename=None, header=None, save_old=True, verbose=None + ): r""" Writes out symbol values in the .config format. The format matches the C implementation, including ordering. @@ -1658,7 +1699,8 @@ def _config_contents(self, header): add(conf_string) elif expr_value(node.dep) and ( - (item is MENU and expr_value(node.visibility)) or item is COMMENT + (item is MENU and expr_value(node.visibility)) + or item is COMMENT ): add("\n#\n# {}\n#\n".format(node.prompt[0])) @@ -1820,7 +1862,11 @@ def sync_deps(self, path): # making a missing symbol logically equivalent to n if sym._write_to_conf: - if sym._old_val is None and sym.orig_type in _BOOL_TRISTATE and val == "n": + if ( + sym._old_val is None + and sym.orig_type in _BOOL_TRISTATE + and val == "n" + ): # No old value (the symbol was missing or n), new value n. # No change. continue @@ -1899,7 +1945,9 @@ def _write_old_vals(self, path): # A separate helper function is neater than complicating write_config() # by passing a flag to it, plus we only need to look at symbols here. - self._write_if_changed(os.path.join(path, "auto.conf"), self._old_vals_contents()) + self._write_if_changed( + os.path.join(path, "auto.conf"), self._old_vals_contents() + ) def _old_vals_contents(self): # _write_old_vals() helper. Returns the contents to write as a string. @@ -2098,15 +2146,21 @@ def status(flag): ( "configuration with {} symbols".format(len(self.syms)), 'main menu prompt "{}"'.format(self.mainmenu_text), - "srctree is current directory" - if not self.srctree - else 'srctree "{}"'.format(self.srctree), + ( + "srctree is current directory" + if not self.srctree + else 'srctree "{}"'.format(self.srctree) + ), 'config symbol prefix "{}"'.format(self.config_prefix), "warnings " + status(self.warn), - "printing of warnings to stderr " + status(self.warn_to_stderr), - "undef. symbol assignment warnings " + status(self.warn_assign_undef), - "overriding symbol assignment warnings " + status(self.warn_assign_override), - "redundant symbol assignment warnings " + status(self.warn_assign_redun), + "printing of warnings to stderr " + + status(self.warn_to_stderr), + "undef. symbol assignment warnings " + + status(self.warn_assign_undef), + "overriding symbol assignment warnings " + + status(self.warn_assign_override), + "redundant symbol assignment warnings " + + status(self.warn_assign_redun), ) ) ) @@ -2145,7 +2199,11 @@ def _open_config(self, filename): filename, errno.errorcode[e.errno], e.strerror, - "set to '{}'".format(self.srctree) if self.srctree else "unset or blank", + ( + "set to '{}'".format(self.srctree) + if self.srctree + else "unset or blank" + ), ), ) @@ -2200,7 +2258,8 @@ def _enter_file(self, filename): self.linenr, rel_filename, "\n".join( - "{}:{}".format(name, linenr) for name, linenr in self._include_path + "{}:{}".format(name, linenr) + for name, linenr in self._include_path ), ) ) @@ -2432,7 +2491,11 @@ def _tokenize(self, s): else: i = match.end() - token = self.const_syms[name] if name in STR_TO_TRI else self._lookup_sym(name) + token = ( + self.const_syms[name] + if name in STR_TO_TRI + else self._lookup_sym(name) + ) else: # It's a case of missing quotes. For example, the @@ -2487,7 +2550,9 @@ def _tokenize(self, s): # The preprocessor functionality changed how # environment variables are referenced, to $(FOO). val = expandvars( - s[i + 1 : end_i - 1].replace("$UNAME_RELEASE", _UNAME_RELEASE) + s[i + 1 : end_i - 1].replace( + "$UNAME_RELEASE", _UNAME_RELEASE + ) ) i = end_i @@ -2679,7 +2744,9 @@ def _parse_assignment(self, s): else: # op == "+=" # += does immediate expansion if the variable was last set # with := - var.value += " " + (val if var.is_recursive else self._expand_whole(val, ())) + var.value += " " + ( + val if var.is_recursive else self._expand_whole(val, ()) + ) def _expand_whole(self, s, args): # Expands preprocessor macros in all of 's'. Used whenever we don't @@ -2837,13 +2904,15 @@ def _fn_val(self, args): # Plain variable if var._n_expansions: self._parse_error( - "Preprocessor variable {} recursively " "references itself".format(var.name) + "Preprocessor variable {} recursively " + "references itself".format(var.name) ) elif var._n_expansions > 100: # Allow functions to call themselves, but guess that functions # that are overly recursive are stuck self._parse_error( - "Preprocessor function {} seems stuck " "in infinite recursion".format(var.name) + "Preprocessor function {} seems stuck " + "in infinite recursion".format(var.name) ) var._n_expansions += 1 @@ -2856,7 +2925,9 @@ def _fn_val(self, args): py_fn, min_arg, max_arg = self._functions[fn] - if len(args) - 1 < min_arg or (max_arg is not None and len(args) - 1 > max_arg): + if len(args) - 1 < min_arg or ( + max_arg is not None and len(args) - 1 > max_arg + ): if min_arg == max_arg: expected_args = min_arg @@ -2868,7 +2939,11 @@ def _fn_val(self, args): raise KconfigError( "{}:{}: bad number of arguments in call " "to {}, expected {}, got {}".format( - self.filename, self.linenr, fn, expected_args, len(args) - 1 + self.filename, + self.linenr, + fn, + expected_args, + len(args) - 1, ) ) @@ -2966,7 +3041,11 @@ def _parse_block(self, end_token, parent, prev): self._parse_props(node) if node.is_menuconfig and not node.prompt: - self._warn("the menuconfig symbol {} has no prompt".format(sym.name_and_loc)) + self._warn( + "the menuconfig symbol {} has no prompt".format( + sym.name_and_loc + ) + ) # Equivalent to # @@ -3007,9 +3086,11 @@ def _parse_block(self, end_token, parent, prev): self.linenr, pattern, self._line.strip(), - "set to '{}'".format(self.srctree) - if self.srctree - else "unset or blank", + ( + "set to '{}'".format(self.srctree) + if self.srctree + else "unset or blank" + ), ) ) @@ -3120,11 +3201,15 @@ def _parse_block(self, end_token, parent, prev): self._parse_error( "no corresponding 'choice'" if t0 is _T_ENDCHOICE - else "no corresponding 'if'" - if t0 is _T_ENDIF - else "no corresponding 'menu'" - if t0 is _T_ENDMENU - else "unrecognized construct" + else ( + "no corresponding 'if'" + if t0 is _T_ENDIF + else ( + "no corresponding 'menu'" + if t0 is _T_ENDMENU + else "unrecognized construct" + ) + ) ) # End of file reached. Return the last node. @@ -3132,11 +3217,11 @@ def _parse_block(self, end_token, parent, prev): if end_token: raise KconfigError( "error: expected '{}' at end of '{}'".format( - "endchoice" - if end_token is _T_ENDCHOICE - else "endif" - if end_token is _T_ENDIF - else "endmenu", + ( + "endchoice" + if end_token is _T_ENDCHOICE + else "endif" if end_token is _T_ENDIF else "endmenu" + ), self.filename, ) ) @@ -3188,7 +3273,9 @@ def _parse_props(self, node): if not self._check_token(_T_ON): self._parse_error("expected 'on' after 'depends'") - node.dep = self._make_and(node.dep, self._expect_expr_and_eol()) + node.dep = self._make_and( + node.dep, self._expect_expr_and_eol() + ) elif t0 is _T_HELP: self._parse_help(node) @@ -3197,36 +3284,52 @@ def _parse_props(self, node): if node.item.__class__ is not Symbol: self._parse_error("only symbols can select") - node.selects.append((self._expect_nonconst_sym(), self._parse_cond())) + node.selects.append( + (self._expect_nonconst_sym(), self._parse_cond()) + ) elif t0 is None: # Blank line continue elif t0 is _T_DEFAULT: - node.defaults.append((self._parse_expr(False), self._parse_cond())) + node.defaults.append( + (self._parse_expr(False), self._parse_cond()) + ) elif t0 in _DEF_TOKEN_TO_TYPE: self._set_type(node.item, _DEF_TOKEN_TO_TYPE[t0]) - node.defaults.append((self._parse_expr(False), self._parse_cond())) + node.defaults.append( + (self._parse_expr(False), self._parse_cond()) + ) elif t0 is _T_PROMPT: self._parse_prompt(node) elif t0 is _T_RANGE: - node.ranges.append((self._expect_sym(), self._expect_sym(), self._parse_cond())) + node.ranges.append( + ( + self._expect_sym(), + self._expect_sym(), + self._parse_cond(), + ) + ) elif t0 is _T_IMPLY: if node.item.__class__ is not Symbol: self._parse_error("only symbols can imply") - node.implies.append((self._expect_nonconst_sym(), self._parse_cond())) + node.implies.append( + (self._expect_nonconst_sym(), self._parse_cond()) + ) elif t0 is _T_VISIBLE: if not self._check_token(_T_IF): self._parse_error("expected 'if' after 'visible'") - node.visibility = self._make_and(node.visibility, self._expect_expr_and_eol()) + node.visibility = self._make_and( + node.visibility, self._expect_expr_and_eol() + ) elif t0 is _T_OPTION: if self._check_token(_T_ENV): @@ -3237,7 +3340,12 @@ def _parse_props(self, node): node.item.env_var = env_var if env_var in os.environ: - node.defaults.append((self._lookup_const_sym(os.environ[env_var]), self.y)) + node.defaults.append( + ( + self._lookup_const_sym(os.environ[env_var]), + self.y, + ) + ) else: self._warn( "{1} has 'option env=\"{0}\"', " @@ -3268,7 +3376,9 @@ def _parse_props(self, node): self._warn( "'option defconfig_list' set on multiple " "symbols ({0} and {1}). Only {0} will be " - "used.".format(self.defconfig_list.name, node.item.name), + "used.".format( + self.defconfig_list.name, node.item.name + ), self.filename, self.linenr, ) @@ -3295,7 +3405,10 @@ def _parse_props(self, node): elif self._check_token(_T_ALLNOCONFIG_Y): if node.item.__class__ is not Symbol: - self._parse_error("the 'allnoconfig_y' option is only " "valid for symbols") + self._parse_error( + "the 'allnoconfig_y' option is only " + "valid for symbols" + ) node.item.is_allnoconfig_y = True @@ -3332,7 +3445,10 @@ def _parse_prompt(self, node): # multiple times if node.prompt: - self._warn(node.item.name_and_loc + " defined with multiple prompts in single location") + self._warn( + node.item.name_and_loc + + " defined with multiple prompts in single location" + ) prompt = self._tokens[1] self._tokens_i = 2 @@ -3341,7 +3457,10 @@ def _parse_prompt(self, node): self._parse_error("expected prompt string") if prompt != prompt.strip(): - self._warn(node.item.name_and_loc + " has leading or trailing whitespace in its prompt") + self._warn( + node.item.name_and_loc + + " has leading or trailing whitespace in its prompt" + ) # This avoid issues for e.g. reStructuredText documentation, where # '*prompt *' is invalid @@ -3492,7 +3611,11 @@ def _parse_factor(self, transform_m): # _T_EQUAL, _T_UNEQUAL, etc., deliberately have the same values as # EQUAL, UNEQUAL, etc., so we can just use the token directly self._tokens_i += 1 - return (self._tokens[self._tokens_i - 1], token, self._expect_sym()) + return ( + self._tokens[self._tokens_i - 1], + token, + self._expect_sym(), + ) if token is _T_NOT: # token == _T_NOT == NOT @@ -3701,37 +3824,46 @@ def _propagate_deps(self, node, visible_if): if cur.prompt: cur.prompt = ( cur.prompt[0], - self._make_and(cur.prompt[1], self._make_and(visible_if, dep)), + self._make_and( + cur.prompt[1], self._make_and(visible_if, dep) + ), ) # Propagate dependencies to defaults if cur.defaults: cur.defaults = [ - (default, self._make_and(cond, dep)) for default, cond in cur.defaults + (default, self._make_and(cond, dep)) + for default, cond in cur.defaults ] # Propagate dependencies to ranges if cur.ranges: cur.ranges = [ - (low, high, self._make_and(cond, dep)) for low, high, cond in cur.ranges + (low, high, self._make_and(cond, dep)) + for low, high, cond in cur.ranges ] # Propagate dependencies to selects if cur.selects: cur.selects = [ - (target, self._make_and(cond, dep)) for target, cond in cur.selects + (target, self._make_and(cond, dep)) + for target, cond in cur.selects ] # Propagate dependencies to implies if cur.implies: cur.implies = [ - (target, self._make_and(cond, dep)) for target, cond in cur.implies + (target, self._make_and(cond, dep)) + for target, cond in cur.implies ] elif cur.prompt: # Not a symbol/choice # Propagate dependencies to the prompt. 'visible if' is only # propagated to symbols/choices. - cur.prompt = (cur.prompt[0], self._make_and(cur.prompt[1], dep)) + cur.prompt = ( + cur.prompt[0], + self._make_and(cur.prompt[1], dep), + ) cur = cur.next @@ -3757,12 +3889,16 @@ def _add_props_to_sym(self, node): # Modify the reverse dependencies of the selected symbol for target, cond in node.selects: - target.rev_dep = self._make_or(target.rev_dep, self._make_and(sym, cond)) + target.rev_dep = self._make_or( + target.rev_dep, self._make_and(sym, cond) + ) # Modify the weak reverse dependencies of the implied # symbol for target, cond in node.implies: - target.weak_rev_dep = self._make_or(target.weak_rev_dep, self._make_and(sym, cond)) + target.weak_rev_dep = self._make_or( + target.weak_rev_dep, self._make_and(sym, cond) + ) # # Misc. @@ -3816,7 +3952,9 @@ def num_ok(sym, type_): raise KconfigError( "the {} symbol {} has a malformed default {} -- " "expected a single symbol".format( - TYPE_TO_STR[sym.orig_type], sym.name_and_loc, expr_str(default) + TYPE_TO_STR[sym.orig_type], + sym.name_and_loc, + expr_str(default), ) ) @@ -3832,13 +3970,16 @@ def num_ok(sym, type_): # (and no symbol named 'foo' exists). self._warn( "style: quotes recommended around " - "default value for string symbol " + sym.name_and_loc + "default value for string symbol " + + sym.name_and_loc ) elif not num_ok(default, sym.orig_type): # INT/HEX self._warn( "the {0} symbol {1} has a non-{0} default {2}".format( - TYPE_TO_STR[sym.orig_type], sym.name_and_loc, default.name_and_loc + TYPE_TO_STR[sym.orig_type], + sym.name_and_loc, + default.name_and_loc, ) ) @@ -3850,7 +3991,9 @@ def num_ok(sym, type_): ) else: # UNKNOWN - self._warn("{} defined without a type".format(sym.name_and_loc)) + self._warn( + "{} defined without a type".format(sym.name_and_loc) + ) if sym.ranges: if sym.orig_type not in _INT_HEX: @@ -3861,7 +4004,9 @@ def num_ok(sym, type_): ) else: for low, high, _ in sym.ranges: - if not num_ok(low, sym.orig_type) or not num_ok(high, sym.orig_type): + if not num_ok(low, sym.orig_type) or not num_ok( + high, sym.orig_type + ): self._warn( "the {0} symbol {1} has a non-{0} " @@ -3880,7 +4025,9 @@ def _check_choice_sanity(self): def warn_select_imply(sym, expr, expr_type): msg = ( "the choice symbol {} is {} by the following symbols, but " - "select/imply has no effect on choice symbols".format(sym.name_and_loc, expr_type) + "select/imply has no effect on choice symbols".format( + sym.name_and_loc, expr_type + ) ) # si = select/imply @@ -3914,7 +4061,9 @@ def warn_select_imply(sym, expr, expr_type): if default.choice is not choice: self._warn( "the default selection {} of {} is not " - "contained in the choice".format(default.name_and_loc, choice.name_and_loc) + "contained in the choice".format( + default.name_and_loc, choice.name_and_loc + ) ) for sym in choice.syms: @@ -3935,19 +4084,27 @@ def warn_select_imply(sym, expr, expr_type): if node.parent.item is choice: if not node.prompt: self._warn( - "the choice symbol {} has no prompt".format(sym.name_and_loc) + "the choice symbol {} has no prompt".format( + sym.name_and_loc + ) ) elif node.prompt: self._warn( "the choice symbol {} is defined with a " - "prompt outside the choice".format(sym.name_and_loc) + "prompt outside the choice".format( + sym.name_and_loc + ) ) def _parse_error(self, msg): raise KconfigError( "{}error: couldn't parse '{}': {}".format( - "" if self.filename is None else "{}:{}: ".format(self.filename, self.linenr), + ( + "" + if self.filename is None + else "{}:{}: ".format(self.filename, self.linenr) + ), self._line.strip(), msg, ) @@ -4031,7 +4188,11 @@ def is_num(s): # symbols, but shouldn't be flagged # # - The MODULES symbol always exists - if not sym.nodes and not is_num(sym.name) and sym.name != "MODULES": + if ( + not sym.nodes + and not is_num(sym.name) + and sym.name != "MODULES" + ): msg = "undefined symbol {}:".format(sym.name) for node in self.node_iter(): @@ -4352,7 +4513,9 @@ def type(self): See the class documentation. """ if self.orig_type is TRISTATE and ( - self.choice and self.choice.tri_value == 2 or not self.kconfig.modules.tri_value + self.choice + and self.choice.tri_value == 2 + or not self.kconfig.modules.tri_value ): return BOOL @@ -4402,7 +4565,9 @@ def str_value(self): # The zeros are from the C implementation running strtoll() # on empty strings low = ( - int(low_expr.str_value, base) if _is_base_n(low_expr.str_value, base) else 0 + int(low_expr.str_value, base) + if _is_base_n(low_expr.str_value, base) + else 0 ) high = ( int(high_expr.str_value, base) @@ -4472,7 +4637,9 @@ def str_value(self): if clamp is not None: # The value is rewritten to a standard form if it is # clamped - val = str(clamp) if self.orig_type is INT else hex(clamp) + val = ( + str(clamp) if self.orig_type is INT else hex(clamp) + ) if has_default: num2str = str if base == 10 else hex @@ -4575,7 +4742,9 @@ def tri_value(self): # m is promoted to y for (1) bool symbols and (2) symbols with a # weak_rev_dep (from imply) of y - if val == 1 and (self.type is BOOL or expr_value(self.weak_rev_dep) == 2): + if val == 1 and ( + self.type is BOOL or expr_value(self.weak_rev_dep) == 2 + ): val = 2 elif vis == 2: @@ -4624,16 +4793,22 @@ def config_string(self): return ( "{}{}={}\n".format(self.kconfig.config_prefix, self.name, val) if val != "n" - else "# {}{} is not set\n".format(self.kconfig.config_prefix, self.name) + else "# {}{} is not set\n".format( + self.kconfig.config_prefix, self.name + ) ) if self.orig_type in _INT_HEX: - return "{}{}={}\n".format(self.kconfig.config_prefix, self.name, val) + return "{}{}={}\n".format( + self.kconfig.config_prefix, self.name, val + ) # sym.orig_type is STRING # hightall, remove quotes # return '{}{}="{}"\n'.format(self.kconfig.config_prefix, self.name, escape(val)) - return '{}{}={}\n'.format(self.kconfig.config_prefix, self.name, escape(val)) + return "{}{}={}\n".format( + self.kconfig.config_prefix, self.name, escape(val) + ) @property def name_and_loc(self): @@ -4717,7 +4892,11 @@ def set_value(self, value): self.kconfig._warn( "the value {} is invalid for {}, which has type {} -- " "assignment ignored".format( - TRI_TO_STR[value] if value in TRI_TO_STR else "'{}'".format(value), + ( + TRI_TO_STR[value] + if value in TRI_TO_STR + else "'{}'".format(value) + ), self.name_and_loc, TYPE_TO_STR[self.orig_type], ) @@ -4870,7 +5049,9 @@ def custom_str(self, sc_expr_str_fn): Works like Symbol.__str__(), but allows a custom format to be used for all symbol/choice references. See expr_str(). """ - return "\n\n".join(node.custom_str(sc_expr_str_fn) for node in self.nodes) + return "\n\n".join( + node.custom_str(sc_expr_str_fn) for node in self.nodes + ) # # Private methods @@ -4901,13 +5082,9 @@ def __init__(self): self.implies = [] self.ranges = [] - self.user_value = ( - self.choice - ) = ( - self.env_var - ) = ( - self._cached_str_val - ) = self._cached_tri_val = self._cached_vis = self._cached_assignable = None + self.user_value = self.choice = self.env_var = self._cached_str_val = ( + self._cached_tri_val + ) = self._cached_vis = self._cached_assignable = None # _write_to_conf is calculated along with the value. If True, the # Symbol gets a .config entry. @@ -4966,9 +5143,9 @@ def _assignable(self): def _invalidate(self): # Marks the symbol as needing to be recalculated - self._cached_str_val = ( - self._cached_tri_val - ) = self._cached_vis = self._cached_assignable = None + self._cached_str_val = self._cached_tri_val = self._cached_vis = ( + self._cached_assignable + ) = None def _rec_invalidate(self): # Invalidates the symbol and all items that (possibly) depend on it @@ -5021,7 +5198,8 @@ def _rec_invalidate_if_has_prompt(self): if self.kconfig._warn_assign_no_prompt: self.kconfig._warn( - self.name_and_loc + " has no prompt, meaning " "user values have no effect on it" + self.name_and_loc + " has no prompt, meaning " + "user values have no effect on it" ) def _str_default(self): @@ -5041,7 +5219,11 @@ def _str_default(self): val = min(expr_value(default), cond_val) break - val = max(expr_value(self.rev_dep), expr_value(self.weak_rev_dep), val) + val = max( + expr_value(self.rev_dep), + expr_value(self.weak_rev_dep), + val, + ) # Transpose mod to yes if type is bool (possibly due to modules # being disabled) @@ -5085,11 +5267,14 @@ def _warn_select_unsatisfied_deps(self): # In both cases, we can split on AND and pick the first operand selecting_sym = split_expr(select, AND)[0] - msg += "\n - {}, with value {}, direct dependencies {} " "(value: {})".format( - selecting_sym.name_and_loc, - selecting_sym.str_value, - expr_str(selecting_sym.direct_dep), - TRI_TO_STR[expr_value(selecting_sym.direct_dep)], + msg += ( + "\n - {}, with value {}, direct dependencies {} " + "(value: {})".format( + selecting_sym.name_and_loc, + selecting_sym.str_value, + expr_str(selecting_sym.direct_dep), + TRI_TO_STR[expr_value(selecting_sym.direct_dep)], + ) ) if select.__class__ is tuple: @@ -5386,7 +5571,11 @@ def set_value(self, value): self.kconfig._warn( "the value {} is invalid for {}, which has type {} -- " "assignment ignored".format( - TRI_TO_STR[value] if value in TRI_TO_STR else "'{}'".format(value), + ( + TRI_TO_STR[value] + if value in TRI_TO_STR + else "'{}'".format(value) + ), self.name_and_loc, TYPE_TO_STR[self.orig_type], ) @@ -5428,7 +5617,10 @@ def __repr__(self): Returns a string with information about the choice when it is evaluated on e.g. the interactive Python prompt. """ - fields = ["choice " + self.name if self.name else "choice", TYPE_TO_STR[self.type]] + fields = [ + "choice " + self.name if self.name else "choice", + TYPE_TO_STR[self.type], + ] add = fields.append for node in self.nodes: @@ -5444,7 +5636,9 @@ def __repr__(self): add("{} selected".format(self.selection.name)) if self.user_selection: - user_sel_str = "{} selected by user".format(self.user_selection.name) + user_sel_str = "{} selected by user".format( + self.user_selection.name + ) if self.selection is not self.user_selection: user_sel_str += " (overridden)" @@ -5479,7 +5673,9 @@ def custom_str(self, sc_expr_str_fn): Works like Choice.__str__(), but allows a custom format to be used for all symbol/choice references. See expr_str(). """ - return "\n\n".join(node.custom_str(sc_expr_str_fn) for node in self.nodes) + return "\n\n".join( + node.custom_str(sc_expr_str_fn) for node in self.nodes + ) # # Private methods @@ -5504,9 +5700,9 @@ def __init__(self): self.syms = [] self.defaults = [] - self.name = ( - self.user_value - ) = self.user_selection = self._cached_vis = self._cached_assignable = None + self.name = self.user_value = self.user_selection = ( + self._cached_vis + ) = self._cached_assignable = None self._cached_selection = _NO_CACHED_SELECTION @@ -5768,14 +5964,18 @@ def orig_defaults(self): """ See the class documentation. """ - return [(default, self._strip_dep(cond)) for default, cond in self.defaults] + return [ + (default, self._strip_dep(cond)) for default, cond in self.defaults + ] @property def orig_selects(self): """ See the class documentation. """ - return [(select, self._strip_dep(cond)) for select, cond in self.selects] + return [ + (select, self._strip_dep(cond)) for select, cond in self.selects + ] @property def orig_implies(self): @@ -5789,7 +5989,10 @@ def orig_ranges(self): """ See the class documentation. """ - return [(low, high, self._strip_dep(cond)) for low, high, cond in self.ranges] + return [ + (low, high, self._strip_dep(cond)) + for low, high, cond in self.ranges + ] @property def referenced(self): @@ -5907,13 +6110,17 @@ def custom_str(self, sc_expr_str_fn): ) def _menu_comment_node_str(self, sc_expr_str_fn): - s = '{} "{}"'.format("menu" if self.item is MENU else "comment", self.prompt[0]) + s = '{} "{}"'.format( + "menu" if self.item is MENU else "comment", self.prompt[0] + ) if self.dep is not self.kconfig.y: s += "\n\tdepends on {}".format(expr_str(self.dep, sc_expr_str_fn)) if self.item is MENU and self.visibility is not self.kconfig.y: - s += "\n\tvisible if {}".format(expr_str(self.visibility, sc_expr_str_fn)) + s += "\n\tvisible if {}".format( + expr_str(self.visibility, sc_expr_str_fn) + ) return s @@ -5929,7 +6136,9 @@ def indent_add_cond(s, cond): sc = self.item if sc.__class__ is Symbol: - lines = [("menuconfig " if self.is_menuconfig else "config ") + sc.name] + lines = [ + ("menuconfig " if self.is_menuconfig else "config ") + sc.name + ] else: lines = ["choice " + sc.name if sc.name else "choice"] @@ -5945,7 +6154,10 @@ def indent_add_cond(s, cond): # Symbol defined without a type (which generates a warning) prefix = "prompt" - indent_add_cond(prefix + ' "{}"'.format(escape(self.prompt[0])), self.orig_prompt[1]) + indent_add_cond( + prefix + ' "{}"'.format(escape(self.prompt[0])), + self.orig_prompt[1], + ) if sc.__class__ is Symbol: if sc.is_allnoconfig_y: @@ -5962,11 +6174,16 @@ def indent_add_cond(s, cond): for low, high, cond in self.orig_ranges: indent_add_cond( - "range {} {}".format(sc_expr_str_fn(low), sc_expr_str_fn(high)), cond + "range {} {}".format( + sc_expr_str_fn(low), sc_expr_str_fn(high) + ), + cond, ) for default, cond in self.orig_defaults: - indent_add_cond("default " + expr_str(default, sc_expr_str_fn), cond) + indent_add_cond( + "default " + expr_str(default, sc_expr_str_fn), cond + ) if sc.__class__ is Choice and sc.is_optional: indent_add("optional") @@ -6055,7 +6272,9 @@ def expanded_value_w_args(self, *args): def __repr__(self): return "".format( - self.name, "recursive" if self.is_recursive else "immediate", self.value + self.name, + "recursive" if self.is_recursive else "immediate", + self.value, ) @@ -6084,7 +6303,9 @@ class InternalError(Exception): class _KconfigIOError(IOError): def __init__(self, ioerror, msg): self.msg = msg - super(_KconfigIOError, self).__init__(ioerror.errno, ioerror.strerror, ioerror.filename) + super(_KconfigIOError, self).__init__( + ioerror.errno, ioerror.strerror, ioerror.filename + ) def __str__(self): return self.msg @@ -6147,15 +6368,19 @@ def expr_value(expr): return 2 * ( comp == 0 if rel is EQUAL - else comp != 0 - if rel is UNEQUAL - else comp < 0 - if rel is LESS - else comp <= 0 - if rel is LESS_EQUAL - else comp > 0 - if rel is GREATER - else comp >= 0 + else ( + comp != 0 + if rel is UNEQUAL + else ( + comp < 0 + if rel is LESS + else ( + comp <= 0 + if rel is LESS_EQUAL + else comp > 0 if rel is GREATER else comp >= 0 + ) + ) + ) ) @@ -6197,14 +6422,16 @@ def expr_str(expr, sc_expr_str_fn=standard_sc_expr_str): if expr[0] is AND: return "{} && {}".format( - _parenthesize(expr[1], OR, sc_expr_str_fn), _parenthesize(expr[2], OR, sc_expr_str_fn) + _parenthesize(expr[1], OR, sc_expr_str_fn), + _parenthesize(expr[2], OR, sc_expr_str_fn), ) if expr[0] is OR: # This turns A && B || C && D into "(A && B) || (C && D)", which is # redundant, but more readable return "{} || {}".format( - _parenthesize(expr[1], AND, sc_expr_str_fn), _parenthesize(expr[2], AND, sc_expr_str_fn) + _parenthesize(expr[1], AND, sc_expr_str_fn), + _parenthesize(expr[2], AND, sc_expr_str_fn), ) if expr[0] is NOT: @@ -6216,7 +6443,9 @@ def expr_str(expr, sc_expr_str_fn=standard_sc_expr_str): # # Relation operands are always symbols (quoted strings are constant # symbols) - return "{} {} {}".format(sc_expr_str_fn(expr[1]), REL_TO_STR[expr[0]], sc_expr_str_fn(expr[2])) + return "{} {} {}".format( + sc_expr_str_fn(expr[1]), REL_TO_STR[expr[0]], sc_expr_str_fn(expr[2]) + ) def expr_items(expr): @@ -6328,7 +6557,8 @@ def standard_kconfig(description=None): import argparse parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, description=description + formatter_class=argparse.RawDescriptionHelpFormatter, + description=description, ) parser.add_argument( @@ -6557,7 +6787,9 @@ def _locs(sc): if sc.nodes: return "(defined at {})".format( - ", ".join("{0.filename}:{0.linenr}".format(node) for node in sc.nodes) + ", ".join( + "{0.filename}:{0.linenr}".format(node) for node in sc.nodes + ) ) return "(undefined)" @@ -6585,11 +6817,15 @@ def _expr_depends_on(expr, sym): elif left is not sym: return False - return (expr[0] is EQUAL and right is sym.kconfig.m or right is sym.kconfig.y) or ( - expr[0] is UNEQUAL and right is sym.kconfig.n - ) + return ( + expr[0] is EQUAL + and right is sym.kconfig.m + or right is sym.kconfig.y + ) or (expr[0] is UNEQUAL and right is sym.kconfig.n) - return expr[0] is AND and (_expr_depends_on(expr[1], sym) or _expr_depends_on(expr[2], sym)) + return expr[0] is AND and ( + _expr_depends_on(expr[1], sym) or _expr_depends_on(expr[2], sym) + ) def _auto_menu_dep(node1, node2): @@ -6597,7 +6833,9 @@ def _auto_menu_dep(node1, node2): # node2 has a prompt, we check its condition. Otherwise, we look directly # at node2.dep. - return _expr_depends_on(node2.prompt[1] if node2.prompt else node2.dep, node1.item) + return _expr_depends_on( + node2.prompt[1] if node2.prompt else node2.dep, node1.item + ) def _flatten(node): @@ -6811,7 +7049,9 @@ def _found_dep_loop(loop, cur): if item.__class__ is Symbol and item.choice: msg += "the choice symbol " - msg += "{}, with definition...\n\n{}\n\n".format(item.name_and_loc, item) + msg += "{}, with definition...\n\n{}\n\n".format( + item.name_and_loc, item + ) # Small wart: Since we reuse the already calculated # Symbol/Choice._dependents sets for recursive dependency detection, we @@ -6828,10 +7068,14 @@ def _found_dep_loop(loop, cur): if item.__class__ is Symbol: if item.rev_dep is not item.kconfig.n: - msg += "(select-related dependencies: {})\n\n".format(expr_str(item.rev_dep)) + msg += "(select-related dependencies: {})\n\n".format( + expr_str(item.rev_dep) + ) if item.weak_rev_dep is not item.kconfig.n: - msg += "(imply-related dependencies: {})\n\n".format(expr_str(item.rev_dep)) + msg += "(imply-related dependencies: {})\n\n".format( + expr_str(item.rev_dep) + ) msg += "...depends again on " + loop[0].name_and_loc @@ -6853,9 +7097,13 @@ def _decoding_error(e, filename, macro_linenr=None): "Problematic data: {}\n" "Reason: {}".format( e.encoding, - "'{}'".format(filename) - if macro_linenr is None - else "output from macro at {}:{}".format(filename, macro_linenr), + ( + "'{}'".format(filename) + if macro_linenr is None + else "output from macro at {}:{}".format( + filename, macro_linenr + ) + ), e.object[max(e.start - 40, 0) : e.end + 40], e.object[e.start : e.end], e.reason, @@ -6900,7 +7148,9 @@ def _warning_if_fn(kconf, _, cond, msg): def _error_if_fn(kconf, _, cond, msg): if cond == "y": - raise KconfigError("{}:{}: {}".format(kconf.filename, kconf.linenr, msg)) + raise KconfigError( + "{}:{}: {}".format(kconf.filename, kconf.linenr, msg) + ) return "" @@ -6921,7 +7171,9 @@ def _shell_fn(kconf, _, command): if stderr: kconf._warn( - "'{}' wrote to stderr: {}".format(command, "\n".join(stderr.splitlines())), + "'{}' wrote to stderr: {}".format( + command, "\n".join(stderr.splitlines()) + ), kconf.filename, kconf.linenr, ) @@ -7173,28 +7425,93 @@ def _shell_fn(kconf, _, command): # Various sets for quick membership tests. Gives a single global lookup and # avoids creating temporary dicts/tuples. -_TYPE_TOKENS = frozenset({_T_BOOL, _T_TRISTATE, _T_INT, _T_HEX, _T_STRING,}) +_TYPE_TOKENS = frozenset( + { + _T_BOOL, + _T_TRISTATE, + _T_INT, + _T_HEX, + _T_STRING, + } +) -_SOURCE_TOKENS = frozenset({_T_SOURCE, _T_RSOURCE, _T_OSOURCE, _T_ORSOURCE,}) +_SOURCE_TOKENS = frozenset( + { + _T_SOURCE, + _T_RSOURCE, + _T_OSOURCE, + _T_ORSOURCE, + } +) -_REL_SOURCE_TOKENS = frozenset({_T_RSOURCE, _T_ORSOURCE,}) +_REL_SOURCE_TOKENS = frozenset( + { + _T_RSOURCE, + _T_ORSOURCE, + } +) # Obligatory (non-optional) sources -_OBL_SOURCE_TOKENS = frozenset({_T_SOURCE, _T_RSOURCE,}) +_OBL_SOURCE_TOKENS = frozenset( + { + _T_SOURCE, + _T_RSOURCE, + } +) -_BOOL_TRISTATE = frozenset({BOOL, TRISTATE,}) +_BOOL_TRISTATE = frozenset( + { + BOOL, + TRISTATE, + } +) -_BOOL_TRISTATE_UNKNOWN = frozenset({BOOL, TRISTATE, UNKNOWN,}) +_BOOL_TRISTATE_UNKNOWN = frozenset( + { + BOOL, + TRISTATE, + UNKNOWN, + } +) -_INT_HEX = frozenset({INT, HEX,}) +_INT_HEX = frozenset( + { + INT, + HEX, + } +) -_SYMBOL_CHOICE = frozenset({Symbol, Choice,}) +_SYMBOL_CHOICE = frozenset( + { + Symbol, + Choice, + } +) -_MENU_COMMENT = frozenset({MENU, COMMENT,}) +_MENU_COMMENT = frozenset( + { + MENU, + COMMENT, + } +) -_EQUAL_UNEQUAL = frozenset({EQUAL, UNEQUAL,}) +_EQUAL_UNEQUAL = frozenset( + { + EQUAL, + UNEQUAL, + } +) -_RELATIONS = frozenset({EQUAL, UNEQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL,}) +_RELATIONS = frozenset( + { + EQUAL, + UNEQUAL, + LESS, + LESS_EQUAL, + GREATER, + GREATER_EQUAL, + } +) # Helper functions for getting compiled regular expressions, with the needed # matching function returned directly as a small optimization. diff --git a/kconfig-lib/menuconfig.py b/kconfig-lib/menuconfig.py index 22422f0ab..cd91a02a1 100644 --- a/kconfig-lib/menuconfig.py +++ b/kconfig-lib/menuconfig.py @@ -395,7 +395,9 @@ def _rgb_to_6cube(rgb): # https://github.com/tmux/tmux/blob/master/colour.c # 48 is the middle ground between 0 and 95. - return tuple(0 if x < 48 else int(round(max(1, (x - 55) / 40))) for x in rgb) + return tuple( + 0 if x < 48 else int(round(max(1, (x - 55) / 40))) for x in rgb + ) def _6cube_to_rgb(r6g6b6): @@ -450,7 +452,11 @@ def _alloc_rgb(rgb, rgb2index={}): # changing their values. color_index = 16 + len(rgb2index) if color_index >= 256: - _warn("Unable to allocate new RGB color ", rgb, ". Too many colors " "allocated.") + _warn( + "Unable to allocate new RGB color ", + rgb, + ". Too many colors " "allocated.", + ) return 0 # Map each RGB component from the range 0-255 to the range 0-1000, which is @@ -472,7 +478,12 @@ def _color_from_num(num): # - If the terminal doesn't support changing color definitions, or if # curses.COLORS < 256, _alloc_rgb() won't touch any color, and all colors # can be returned as-is - if num < 16 or num > 255 or not curses.can_change_color() or curses.COLORS < 256: + if ( + num < 16 + or num > 255 + or not curses.can_change_color() + or curses.COLORS < 256 + ): return num # _alloc_rgb() might redefine colors, so emulate the xterm 256-color @@ -481,7 +492,9 @@ def _color_from_num(num): if num < 232: num -= 16 - return _alloc_rgb(_6cube_to_rgb(((num // 36) % 6, (num // 6) % 6, num % 6))) + return _alloc_rgb( + _6cube_to_rgb(((num // 36) % 6, (num // 6) % 6, num % 6)) + ) return _alloc_rgb(_gray_to_rgb(num - 232)) @@ -525,7 +538,12 @@ def dist(r1, r2): best = -1 for color in range(curses.COLORS): # ncurses uses the range 0..1000. Scale that down to 0..255. - d = dist(rgb, tuple(int(round(255 * c / 1000)) for c in curses.color_content(color))) + d = dist( + rgb, + tuple( + int(round(255 * c / 1000)) for c in curses.color_content(color) + ), + ) if d < min_dist: min_dist = d best = color @@ -583,7 +601,11 @@ def parse_color(color_def): # HTML format, #RRGGBB if re.match("#[A-Fa-f0-9]{6}", color_def): return _color_from_rgb( - (int(color_def[1:3], 16), int(color_def[3:5], 16), int(color_def[5:7], 16)) + ( + int(color_def[1:3], 16), + int(color_def[3:5], 16), + int(color_def[5:7], 16), + ) ) if color_def in _NAMED_COLORS: @@ -592,13 +614,19 @@ def parse_color(color_def): try: color_num = _color_from_num(int(color_def, 0)) except ValueError: - _warn("Ignoring color", color_def, "that's neither " "predefined nor a number") + _warn( + "Ignoring color", + color_def, + "that's neither " "predefined nor a number", + ) return -1 if not -1 <= color_num < curses.COLORS: _warn( "Ignoring color {}, which is outside the range " - "-1..curses.COLORS-1 (-1..{})".format(color_def, curses.COLORS - 1) + "-1..curses.COLORS-1 (-1..{})".format( + color_def, curses.COLORS - 1 + ) ) return -1 @@ -673,7 +701,9 @@ def _style_attr(fg_color, bg_color, attribs, color_attribs={}): # Create new color pair. Color pair number 0 is hardcoded and cannot be # changed, hence the +1s. curses.init_pair(len(color_attribs) + 1, fg_color, bg_color) - color_attribs[(fg_color, bg_color)] = curses.color_pair(len(color_attribs) + 1) + color_attribs[(fg_color, bg_color)] = curses.color_pair( + len(color_attribs) + 1 + ) return color_attribs[(fg_color, bg_color)] | attribs @@ -925,14 +955,18 @@ def _menuconfig(stdscr): _load_dialog() elif c in ("s", "S"): - filename = _save_dialog(_kconf.write_config, _conf_filename, "configuration") + filename = _save_dialog( + _kconf.write_config, _conf_filename, "configuration" + ) if filename: _conf_filename = filename _conf_changed = False elif c in ("d", "D"): filename = _save_dialog( - _kconf.write_min_config, _minconf_filename, "minimal configuration" + _kconf.write_min_config, + _minconf_filename, + "minimal configuration", ) if filename: _minconf_filename = filename @@ -971,14 +1005,20 @@ def _quit_dialog(): return "No changes to save (for '{}')".format(_conf_filename) while True: - c = _key_dialog("Quit", " Save configuration?\n" "\n" "(Y)es (N)o (C)ancel", "ync") + c = _key_dialog( + "Quit", + " Save configuration?\n" "\n" "(Y)es (N)o (C)ancel", + "ync", + ) if c is None or c == "c": return None if c == "y": # Returns a message to print - msg = _try_save(_kconf.write_config, _conf_filename, "configuration") + msg = _try_save( + _kconf.write_config, _conf_filename, "configuration" + ) if msg: return msg @@ -1069,7 +1109,9 @@ def _resize_main(): _top_sep_win.resize(1, screen_width) _bot_sep_win.resize(1, screen_width) - help_win_height = _SHOW_HELP_HEIGHT if _show_help else len(_MAIN_HELP_LINES) + help_win_height = ( + _SHOW_HELP_HEIGHT if _show_help else len(_MAIN_HELP_LINES) + ) menu_win_height = screen_height - help_win_height - 3 @@ -1178,7 +1220,9 @@ def _jump_to(node): _parent_screen_rows = [] old_show_all = _show_all - jump_into = (isinstance(node.item, Choice) or node.item == MENU) and node.list + jump_into = ( + isinstance(node.item, Choice) or node.item == MENU + ) and node.list # If we're jumping to a non-empty choice or menu, jump to the first entry # in it instead of jumping to its menu node @@ -1352,7 +1396,8 @@ def _center_vertically(): global _menu_scroll _menu_scroll = min( - max(_sel_node_i - _height(_menu_win) // 2, 0), _max_scroll(_shown, _menu_win) + max(_sel_node_i - _height(_menu_win) // 2, 0), + _max_scroll(_shown, _menu_win), ) @@ -1378,7 +1423,10 @@ def _draw_main(): # Add the 'mainmenu' text as the title, centered at the top _safe_addstr( - _top_sep_win, 0, max((term_width - len(_kconf.mainmenu_text)) // 2, 0), _kconf.mainmenu_text + _top_sep_win, + 0, + max((term_width - len(_kconf.mainmenu_text)) // 2, 0), + _kconf.mainmenu_text, ) _top_sep_win.noutrefresh() @@ -1393,7 +1441,9 @@ def _draw_main(): # Draw the _shown nodes starting from index _menu_scroll up to either as # many as fit in the window, or to the end of _shown - for i in range(_menu_scroll, min(_menu_scroll + _height(_menu_win), len(_shown))): + for i in range( + _menu_scroll, min(_menu_scroll + _height(_menu_win), len(_shown)) + ): node = _shown[i] @@ -1474,7 +1524,9 @@ def _draw_main(): # Promptless choices can be entered in show-all mode. Use # standard_sc_expr_str() for them, so they show up as # ''. - menu_prompts.append(menu.prompt[0] if menu.prompt else standard_sc_expr_str(menu.item)) + menu_prompts.append( + menu.prompt[0] if menu.prompt else standard_sc_expr_str(menu.item) + ) menu = menu.parent menu_prompts.append("(Top)") menu_prompts.reverse() @@ -1564,7 +1616,11 @@ def rec(node): # or part of the choice is copied in multiple locations (e.g. by # including some Kconfig file multiple times). We give the prompts at # the current location precedence. - seen_syms = {node.item for node in rec(menu.list) if isinstance(node.item, Symbol)} + seen_syms = { + node.item + for node in rec(menu.list) + if isinstance(node.item, Symbol) + } res = [] for choice_node in menu.item.nodes: for node in rec(choice_node.list): @@ -1608,7 +1664,9 @@ def _change_node(node): while True: s = _input_dialog( - "{} ({})".format(node.prompt[0], TYPE_TO_STR[sc.orig_type]), s, _range_info(sc) + "{} ({})".format(node.prompt[0], TYPE_TO_STR[sc.orig_type]), + s, + _range_info(sc), ) if s is None: @@ -1661,7 +1719,11 @@ def _changeable(node): if not (node.prompt and expr_value(node.prompt[1])): return False - return sc.orig_type in (STRING, INT, HEX) or len(sc.assignable) > 1 or _is_y_mode_choice_sym(sc) + return ( + sc.orig_type in (STRING, INT, HEX) + or len(sc.assignable) > 1 + or _is_y_mode_choice_sym(sc) + ) def _set_sel_node_tri_val(tri_val): @@ -1794,12 +1856,16 @@ def _resize_input_dialog(win, title, info_lines): win_height = min(win_height, screen_height) win_width = max( - _INPUT_DIALOG_MIN_WIDTH, len(title) + 4, *(len(line) + 4 for line in info_lines) + _INPUT_DIALOG_MIN_WIDTH, + len(title) + 4, + *(len(line) + 4 for line in info_lines) ) win_width = min(win_width, screen_width) win.resize(win_height, win_width) - win.mvwin((screen_height - win_height) // 2, (screen_width - win_width) // 2) + win.mvwin( + (screen_height - win_height) // 2, (screen_width - win_width) // 2 + ) def _draw_input_dialog(win, title, info_lines, s, i, hscroll): @@ -1809,7 +1875,13 @@ def _draw_input_dialog(win, title, info_lines, s, i, hscroll): # Note: Perhaps having a separate window for the input field would be nicer visible_s = s[hscroll : hscroll + edit_width] - _safe_addstr(win, 2, 2, visible_s + " " * (edit_width - len(visible_s)), _style["edit"]) + _safe_addstr( + win, + 2, + 2, + visible_s + " " * (edit_width - len(visible_s)), + _style["edit"], + ) for linenr, line in enumerate(info_lines): _safe_addstr(win, 4 + linenr, 2, line) @@ -1904,7 +1976,9 @@ def _save_dialog(save_fn, default_filename, description): filename = default_filename while True: filename = _input_dialog( - "Filename to save {} to".format(description), filename, _load_save_info() + "Filename to save {} to".format(description), + filename, + _load_save_info(), ) if filename is None: return None @@ -1999,7 +2073,9 @@ def _resize_key_dialog(win, text): win_width = min(max(len(line) for line in lines) + 4, screen_width) win.resize(win_height, win_width) - win.mvwin((screen_height - win_height) // 2, (screen_width - win_width) // 2) + win.mvwin( + (screen_height - win_height) // 2, (screen_width - win_width) // 2 + ) def _draw_key_dialog(win, title, text): @@ -2064,7 +2140,9 @@ def _jump_to_dialog(): help_win = _styled_win("help") # Give windows their initial size - _resize_jump_to_dialog(edit_box, matches_win, bot_sep_win, help_win, sel_node_i, scroll) + _resize_jump_to_dialog( + edit_box, matches_win, bot_sep_win, help_win, sel_node_i, scroll + ) _safe_curs_set(2) @@ -2107,7 +2185,9 @@ def select_prev_match(): # matches anywhere in the string. # # It's not horrible either way. Just a bit smoother. - regex_searches = [re.compile(regex).search for regex in s.lower().split()] + regex_searches = [ + re.compile(regex).search for regex in s.lower().split() + ] # No exception thrown, so the regexes are okay bad_re = None @@ -2196,7 +2276,12 @@ def select_prev_match(): # the list when the terminal is resized, hence the 'scroll' # assignment scroll = _resize_jump_to_dialog( - edit_box, matches_win, bot_sep_win, help_win, sel_node_i, scroll + edit_box, + matches_win, + bot_sep_win, + help_win, + sel_node_i, + scroll, ) elif c == "\x06": # \x06 = Ctrl-F @@ -2206,7 +2291,12 @@ def select_prev_match(): _safe_curs_set(2) scroll = _resize_jump_to_dialog( - edit_box, matches_win, bot_sep_win, help_win, sel_node_i, scroll + edit_box, + matches_win, + bot_sep_win, + help_win, + sel_node_i, + scroll, ) elif c == curses.KEY_DOWN: @@ -2234,7 +2324,9 @@ def select_prev_match(): sel_node_i = scroll = 0 else: - s, s_i, hscroll = _edit_text(c, s, s_i, hscroll, _width(edit_box) - 2) + s, s_i, hscroll = _edit_text( + c, s, s_i, hscroll, _width(edit_box) - 2 + ) # Obscure Python: We never pass a value for cached_nodes, and it keeps pointing @@ -2246,13 +2338,17 @@ def _sorted_sc_nodes(cached_nodes=[]): if not cached_nodes: # Add symbol nodes - for sym in sorted(_kconf.unique_defined_syms, key=lambda sym: sym.name): + for sym in sorted( + _kconf.unique_defined_syms, key=lambda sym: sym.name + ): # += is in-place for lists cached_nodes += sym.nodes # Add choice nodes - choices = sorted(_kconf.unique_choices, key=lambda choice: choice.name or "") + choices = sorted( + _kconf.unique_choices, key=lambda choice: choice.name or "" + ) cached_nodes += sorted( [node for choice in choices for node in choice.nodes], @@ -2277,7 +2373,9 @@ def prompt_text(mc): return cached_nodes -def _resize_jump_to_dialog(edit_box, matches_win, bot_sep_win, help_win, sel_node_i, scroll): +def _resize_jump_to_dialog( + edit_box, matches_win, bot_sep_win, help_win, sel_node_i, scroll +): # Resizes the jump-to dialog to fill the terminal. # # Returns the new scroll index. We adjust the scroll if needed so that the @@ -2340,7 +2438,9 @@ def _draw_jump_to_dialog( matches_win.erase() if matches: - for i in range(scroll, min(scroll + _height(matches_win), len(matches))): + for i in range( + scroll, min(scroll + _height(matches_win), len(matches)) + ): node = matches[i] @@ -2402,7 +2502,14 @@ def _draw_jump_to_dialog( # Draw arrows pointing up if the symbol list is scrolled down if scroll > 0: # TODO: Bit ugly that _style["frame"] is repeated here - _safe_hline(edit_box, 2, 4, curses.ACS_UARROW, _N_SCROLL_ARROWS, _style["frame"]) + _safe_hline( + edit_box, + 2, + 4, + curses.ACS_UARROW, + _N_SCROLL_ARROWS, + _style["frame"], + ) visible_s = s[hscroll : hscroll + edit_width] _safe_addstr(edit_box, 1, 1, visible_s) @@ -2443,7 +2550,9 @@ def _info_dialog(node, from_jump_to_dialog): scroll = 0 while True: - _draw_info_dialog(node, lines, scroll, top_line_win, text_win, bot_sep_win, help_win) + _draw_info_dialog( + node, lines, scroll, top_line_win, text_win, bot_sep_win, help_win + ) curses.doupdate() c = _getch_compat(text_win) @@ -2527,7 +2636,9 @@ def _resize_info_dialog(top_line_win, text_win, bot_sep_win, help_win): win.mvwin(0, 0) -def _draw_info_dialog(node, lines, scroll, top_line_win, text_win, bot_sep_win, help_win): +def _draw_info_dialog( + node, lines, scroll, top_line_win, text_win, bot_sep_win, help_win +): text_win_height, text_win_width = text_win.getmaxyx() @@ -2582,13 +2693,15 @@ def _draw_info_dialog(node, lines, scroll, top_line_win, text_win, bot_sep_win, title = ( "Symbol" if isinstance(node.item, Symbol) - else "Choice" - if isinstance(node.item, Choice) - else "Menu" - if node.item == MENU - else "Comment" + else ( + "Choice" + if isinstance(node.item, Choice) + else "Menu" if node.item == MENU else "Comment" + ) ) + " information" - _safe_addstr(top_line_win, 0, max((text_win_width - len(title)) // 2, 0), title) + _safe_addstr( + top_line_win, 0, max((text_win_width - len(title)) // 2, 0), title + ) top_line_win.noutrefresh() @@ -2656,7 +2769,9 @@ def _value_info(sym): # Only put quotes around the value for string symbols return "Value: {}\n".format( - '"{}"'.format(sym.str_value) if sym.orig_type == STRING else sym.str_value + '"{}"'.format(sym.str_value) + if sym.orig_type == STRING + else sym.str_value ) @@ -2699,7 +2814,8 @@ def _direct_dep_info(sc): "" if sc.direct_dep is _kconf.y else "Direct dependencies (={}):\n{}\n".format( - TRI_TO_STR[expr_value(sc.direct_dep)], _split_expr_info(sc.direct_dep, 2) + TRI_TO_STR[expr_value(sc.direct_dep)], + _split_expr_info(sc.direct_dep, 2), ) ) @@ -2759,7 +2875,9 @@ def _split_expr_info(expr, indent): s = "" for i, term in enumerate(split_expr(expr, split_op)): - s += "{}{} {}".format(indent * " ", " " if i == 0 else op_str, _expr_str(term)) + s += "{}{} {}".format( + indent * " ", " " if i == 0 else op_str, _expr_str(term) + ) # Don't bother showing the value hint if the expression is just a # single symbol. _expr_str() already shows its value. @@ -2790,14 +2908,30 @@ def sis(expr, val, title): s = "" if sym.rev_dep is not _kconf.n: - s += sis(sym.rev_dep, 2, "Symbols currently y-selecting this symbol:\n") - s += sis(sym.rev_dep, 1, "Symbols currently m-selecting this symbol:\n") - s += sis(sym.rev_dep, 0, "Symbols currently n-selecting this symbol (no effect):\n") + s += sis( + sym.rev_dep, 2, "Symbols currently y-selecting this symbol:\n" + ) + s += sis( + sym.rev_dep, 1, "Symbols currently m-selecting this symbol:\n" + ) + s += sis( + sym.rev_dep, + 0, + "Symbols currently n-selecting this symbol (no effect):\n", + ) if sym.weak_rev_dep is not _kconf.n: - s += sis(sym.weak_rev_dep, 2, "Symbols currently y-implying this symbol:\n") - s += sis(sym.weak_rev_dep, 1, "Symbols currently m-implying this symbol:\n") - s += sis(sym.weak_rev_dep, 0, "Symbols currently n-implying this symbol (no effect):\n") + s += sis( + sym.weak_rev_dep, 2, "Symbols currently y-implying this symbol:\n" + ) + s += sis( + sym.weak_rev_dep, 1, "Symbols currently m-implying this symbol:\n" + ) + s += sis( + sym.weak_rev_dep, + 0, + "Symbols currently n-implying this symbol (no effect):\n", + ) return s @@ -2837,7 +2971,10 @@ def _include_path_info(node): return "" return "Included via {}\n".format( - " -> ".join("{}:{}".format(filename, linenr) for filename, linenr in node.include_path) + " -> ".join( + "{}:{}".format(filename, linenr) + for filename, linenr in node.include_path + ) ) @@ -2852,7 +2989,15 @@ def _menu_path_info(node): # Promptless choices might appear among the parents. Use # standard_sc_expr_str() for them, so that they show up as # ''. - path = " -> " + (node.prompt[0] if node.prompt else standard_sc_expr_str(node.item)) + path + path = ( + " -> " + + ( + node.prompt[0] + if node.prompt + else standard_sc_expr_str(node.item) + ) + + path + ) return "(Top)" + path @@ -3086,7 +3231,9 @@ def _should_show_name(node): # The 'not node.prompt' case only hits in show-all mode, for promptless # symbols and choices - return not node.prompt or (_show_name and isinstance(node.item, (Symbol, Choice))) + return not node.prompt or ( + _show_name and isinstance(node.item, (Symbol, Choice)) + ) def _value_str(node): @@ -3142,7 +3289,11 @@ def _check_valid(sym, s): try: int(s, base) except ValueError: - _error("'{}' is a malformed {} value".format(s, TYPE_TO_STR[sym.orig_type])) + _error( + "'{}' is a malformed {} value".format( + s, TYPE_TO_STR[sym.orig_type] + ) + ) return False for low_sym, high_sym, cond in sym.ranges: @@ -3151,7 +3302,9 @@ def _check_valid(sym, s): high_s = high_sym.str_value if not int(low_s, base) <= int(s, base) <= int(high_s, base): - _error("{} is outside the range {}-{}".format(s, low_s, high_s)) + _error( + "{} is outside the range {}-{}".format(s, low_s, high_s) + ) return False break diff --git a/kconfig-lib/oldconfig.py b/kconfig-lib/oldconfig.py index 78ed39e20..96d002a67 100644 --- a/kconfig-lib/oldconfig.py +++ b/kconfig-lib/oldconfig.py @@ -100,7 +100,9 @@ def oldconfig(node): while True: val = input( "{} ({}) [{}] ".format( - node.prompt[0], _name_and_loc_str(sym), _default_value_str(sym) + node.prompt[0], + _name_and_loc_str(sym), + _default_value_str(sym), ) ) @@ -141,7 +143,11 @@ def oldconfig(node): # symbols get demoted to n-visibility in y-mode choices, and the # user-selected symbol had visibility y.) for sym in choice.syms: - if sym is not choice.user_selection and sym.visibility and sym.user_value is None: + if ( + sym is not choice.user_selection + and sym.visibility + and sym.user_value is None + ): # New visible symbols in the choice break else: @@ -223,7 +229,9 @@ def _name_and_loc_str(sc): return "{}, defined at {}".format( sc.name or "choice", - ", ".join("{}:{}".format(node.filename, node.linenr) for node in sc.nodes), + ", ".join( + "{}:{}".format(node.filename, node.linenr) for node in sc.nodes + ), ) @@ -239,7 +247,10 @@ def _default_value_str(sym): # For string/int/hex, returns the default value as-is. if sym.type in (BOOL, TRISTATE): - return "/".join(("NMY" if sym.tri_value == tri else "nmy")[tri] for tri in sym.assignable) + return "/".join( + ("NMY" if sym.tri_value == tri else "nmy")[tri] + for tri in sym.assignable + ) # string/int/hex return sym.str_value diff --git a/src/agent/docker-rest-agent/intergration-test/test.py b/src/agent/docker-rest-agent/intergration-test/test.py index 477953681..7a314a2ab 100644 --- a/src/agent/docker-rest-agent/intergration-test/test.py +++ b/src/agent/docker-rest-agent/intergration-test/test.py @@ -5,74 +5,82 @@ client = docker.from_env() -with open('msp.zip', 'rb') as node_msp, open('tls.zip', 'rb') as tls, open('block.zip', 'rb') as block, open('peer_config.zip', 'rb') as peer_config, open('orderer_config.zip', 'rb') as orderer_config: +with open("msp.zip", "rb") as node_msp, open("tls.zip", "rb") as tls, open( + "block.zip", "rb" +) as block, open("peer_config.zip", "rb") as peer_config, open( + "orderer_config.zip", "rb" +) as orderer_config: data = { - 'msp':base64.b64encode(node_msp.read()), - 'tls':base64.b64encode(tls.read()), - 'bootstrap_block':base64.b64encode(block.read()), - 'peer_config_file':base64.b64encode(peer_config.read()), - 'orderer_config_file':base64.b64encode(orderer_config.read()), - 'img': 'hyperledger/cello-hlf:2.2.0', - 'cmd': 'bash /tmp/init.sh "peer node start"', - 'name': 'cello-hlf-peer' + "msp": base64.b64encode(node_msp.read()), + "tls": base64.b64encode(tls.read()), + "bootstrap_block": base64.b64encode(block.read()), + "peer_config_file": base64.b64encode(peer_config.read()), + "orderer_config_file": base64.b64encode(orderer_config.read()), + "img": "hyperledger/cello-hlf:2.2.0", + "cmd": 'bash /tmp/init.sh "peer node start"', + "name": "cello-hlf-peer", } -print('-'*20) -print('Test creating a node') +print("-" * 20) +print("Test creating a node") print() -n = post('http://localhost:5001/api/v1/nodes', data=data) +n = post("http://localhost:5001/api/v1/nodes", data=data) print(n.text) txt = json.loads(n.text) -nid = txt['data']['id'] -print('-'*20) +nid = txt["data"]["id"] +print("-" * 20) -print('Test starting a node') +print("Test starting a node") print() -data = {'action': 'start'} -response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +data = {"action": "start"} +response = post("http://localhost:5001/api/v1/nodes/" + nid, data=data) print(response.text) -print('-'*20) +print("-" * 20) -print('Test restarting a node') +print("Test restarting a node") print() -data = {'action': 'restart'} -response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +data = {"action": "restart"} +response = post("http://localhost:5001/api/v1/nodes/" + nid, data=data) print(response.text) -print('-'*20) +print("-" * 20) -print('Test updating a node') +print("Test updating a node") print() # TODO(dixing): use different commands & configuration files -with open('msp.zip', 'rb') as node_msp, open('tls.zip', 'rb') as tls, open('block.zip', 'rb') as block, open('peer_config.zip', 'rb') as peer_config, open('orderer_config.zip', 'rb') as orderer_config: +with open("msp.zip", "rb") as node_msp, open("tls.zip", "rb") as tls, open( + "block.zip", "rb" +) as block, open("peer_config.zip", "rb") as peer_config, open( + "orderer_config.zip", "rb" +) as orderer_config: data = { - 'action': 'update', - 'msp':base64.b64encode(node_msp.read()), - 'tls':base64.b64encode(tls.read()), - 'bootstrap_block':base64.b64encode(block.read()), - 'peer_config_file':base64.b64encode(peer_config.read()), - 'orderer_config_file':base64.b64encode(orderer_config.read()), - 'cmd': 'bash /tmp/update.sh "peer node start"', + "action": "update", + "msp": base64.b64encode(node_msp.read()), + "tls": base64.b64encode(tls.read()), + "bootstrap_block": base64.b64encode(block.read()), + "peer_config_file": base64.b64encode(peer_config.read()), + "orderer_config_file": base64.b64encode(orderer_config.read()), + "cmd": 'bash /tmp/update.sh "peer node start"', } -response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +response = post("http://localhost:5001/api/v1/nodes/" + nid, data=data) print(response.text) -print('-'*20) +print("-" * 20) -print('Test stopping a node') +print("Test stopping a node") print() -data = {'action': 'stop'} -response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +data = {"action": "stop"} +response = post("http://localhost:5001/api/v1/nodes/" + nid, data=data) print(response.text) -print('-'*20) +print("-" * 20) -print('Get status of a node') +print("Get status of a node") print() -response = get('http://localhost:5001/api/v1/nodes/'+nid) +response = get("http://localhost:5001/api/v1/nodes/" + nid) print(response.text) -print('-'*20) +print("-" * 20) -print('Test deleting a node') +print("Test deleting a node") print() -data = {'action': 'delete'} -response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +data = {"action": "delete"} +response = post("http://localhost:5001/api/v1/nodes/" + nid, data=data) print(response.text) diff --git a/src/agent/docker-rest-agent/server.py b/src/agent/docker-rest-agent/server.py index ee2630a22..2ccd6fd3c 100644 --- a/src/agent/docker-rest-agent/server.py +++ b/src/agent/docker-rest-agent/server.py @@ -8,185 +8,204 @@ logging.basicConfig(level=logging.INFO) app = Flask(__name__) -PASS_CODE = 'OK' -FAIL_CODE = 'Fail' +PASS_CODE = "OK" +FAIL_CODE = "Fail" docker_url = os.getenv("DOCKER_URL") storage_path = os.getenv("STORAGE_PATH") client = docker.DockerClient(docker_url) -res = {'code': '', 'data': {}, 'msg': ''} +res = {"code": "", "data": {}, "msg": ""} -@app.route('/api/v1/networks', methods=['GET']) + +@app.route("/api/v1/networks", methods=["GET"]) def get_network(): container_list = client.containers.list() containers = {} for container in container_list: - containers[container.id]={ - "id":container.id, - "short_id":container.short_id, - "name":container.name, - "status":container.status, - "image":str(container.image), - "attrs":container.attrs + containers[container.id] = { + "id": container.id, + "short_id": container.short_id, + "name": container.name, + "status": container.status, + "image": str(container.image), + "attrs": container.attrs, } - res = {'code':PASS_CODE, 'data':containers, 'msg':''} - return jsonify({'res':res}) + res = {"code": PASS_CODE, "data": containers, "msg": ""} + return jsonify({"res": res}) + -@app.route('/api/v1/nodes', methods=['POST']) +@app.route("/api/v1/nodes", methods=["POST"]) def create_node(): - node_name = request.form.get('name') + node_name = request.form.get("name") env = { - 'HLF_NODE_MSP': request.form.get('msp'), - 'HLF_NODE_TLS':request.form.get('tls'), - 'HLF_NODE_PEER_CONFIG':request.form.get('peer_config_file'), - 'HLF_NODE_ORDERER_CONFIG':request.form.get('orderer_config_file'), - 'platform': 'linux/amd64', + "HLF_NODE_MSP": request.form.get("msp"), + "HLF_NODE_TLS": request.form.get("tls"), + "HLF_NODE_PEER_CONFIG": request.form.get("peer_config_file"), + "HLF_NODE_ORDERER_CONFIG": request.form.get("orderer_config_file"), + "platform": "linux/amd64", } port_map = ast.literal_eval(request.form.get("port_map")) - volumes = [ - '{}/fabric/{}:/etc/hyperledger/fabric'.format(storage_path, node_name), - '{}/production/{}:/var/hyperledger/production'.format(storage_path, node_name), - '/var/run/docker.sock:/host/var/run/docker.sock' + volumes = [ + "{}/fabric/{}:/etc/hyperledger/fabric".format(storage_path, node_name), + "{}/production/{}:/var/hyperledger/production".format( + storage_path, node_name + ), + "/var/run/docker.sock:/host/var/run/docker.sock", ] - if request.form.get('type') == "peer": + if request.form.get("type") == "peer": peer_envs = { - 'CORE_VM_ENDPOINT': 'unix:///host/var/run/docker.sock', - 'CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE': 'cello-net', - 'FABRIC_LOGGING_SPEC': 'INFO', - 'CORE_PEER_TLS_ENABLED': 'true', - 'CORE_PEER_PROFILE_ENABLED': 'false', - 'CORE_PEER_TLS_CERT_FILE': '/etc/hyperledger/fabric/tls/server.crt', - 'CORE_PEER_TLS_KEY_FILE': '/etc/hyperledger/fabric/tls/server.key', - 'CORE_PEER_TLS_ROOTCERT_FILE': '/etc/hyperledger/fabric/tls/ca.crt', - 'CORE_PEER_ID': node_name, - 'CORE_PEER_ADDRESS': node_name +":7051", - 'CORE_PEER_LISTENADDRESS': '0.0.0.0:7051', - 'CORE_PEER_CHAINCODEADDRESS': node_name+":7052", - 'CORE_PEER_CHAINCODELISTENADDRESS':'0.0.0.0:7052', - 'CORE_PEER_GOSSIP_BOOTSTRAP': node_name+":7051", - 'CORE_PEER_GOSSIP_EXTERNALENDPOINT': node_name+":7051", - 'CORE_PEER_LOCALMSPID': node_name.split('.')[1].capitalize()+'MSP', - 'CORE_PEER_MSPCONFIGPATH': '/etc/hyperledger/fabric/msp', - 'CORE_OPERATIONS_LISTENADDRESS': node_name+":9444", - 'CORE_METRICS_PROVIDER': 'prometheus' + "CORE_VM_ENDPOINT": "unix:///host/var/run/docker.sock", + "CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE": "cello-net", + "FABRIC_LOGGING_SPEC": "INFO", + "CORE_PEER_TLS_ENABLED": "true", + "CORE_PEER_PROFILE_ENABLED": "false", + "CORE_PEER_TLS_CERT_FILE": "/etc/hyperledger/fabric/tls/server.crt", + "CORE_PEER_TLS_KEY_FILE": "/etc/hyperledger/fabric/tls/server.key", + "CORE_PEER_TLS_ROOTCERT_FILE": "/etc/hyperledger/fabric/tls/ca.crt", + "CORE_PEER_ID": node_name, + "CORE_PEER_ADDRESS": node_name + ":7051", + "CORE_PEER_LISTENADDRESS": "0.0.0.0:7051", + "CORE_PEER_CHAINCODEADDRESS": node_name + ":7052", + "CORE_PEER_CHAINCODELISTENADDRESS": "0.0.0.0:7052", + "CORE_PEER_GOSSIP_BOOTSTRAP": node_name + ":7051", + "CORE_PEER_GOSSIP_EXTERNALENDPOINT": node_name + ":7051", + "CORE_PEER_LOCALMSPID": node_name.split(".")[1].capitalize() + + "MSP", + "CORE_PEER_MSPCONFIGPATH": "/etc/hyperledger/fabric/msp", + "CORE_OPERATIONS_LISTENADDRESS": node_name + ":9444", + "CORE_METRICS_PROVIDER": "prometheus", } env.update(peer_envs) else: - order_envs = { - 'FABRIC_LOGGING_SPEC':'INFO', - 'ORDERER_GENERAL_LISTENADDRESS': '0.0.0.0', - 'ORDERER_GENERAL_LISTENPORT': '7050', - 'ORDERER_GENERAL_LOCALMSPID': 'OrdererMSP', - 'ORDERER_GENERAL_LOCALMSPDIR': '/etc/hyperledger/fabric/msp', - 'ORDERER_GENERAL_TLS_ENABLED': 'true', - 'ORDERER_GENERAL_TLS_PRIVATEKEY':'/etc/hyperledger/fabric/tls/server.key', - 'ORDERER_GENERAL_TLS_CERTIFICATE':'/etc/hyperledger/fabric/tls/server.crt', - 'ORDERER_GENERAL_TLS_ROOTCAS': '[/etc/hyperledger/fabric/tls/ca.crt]', - 'ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE': '/etc/hyperledger/fabric/tls/server.crt', - 'ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY': '/etc/hyperledger/fabric/tls/server.key', - 'ORDERER_GENERAL_CLUSTER_ROOTCAS': '[/etc/hyperledger/fabric/tls/ca.crt]', + order_envs = { + "FABRIC_LOGGING_SPEC": "INFO", + "ORDERER_GENERAL_LISTENADDRESS": "0.0.0.0", + "ORDERER_GENERAL_LISTENPORT": "7050", + "ORDERER_GENERAL_LOCALMSPID": "OrdererMSP", + "ORDERER_GENERAL_LOCALMSPDIR": "/etc/hyperledger/fabric/msp", + "ORDERER_GENERAL_TLS_ENABLED": "true", + "ORDERER_GENERAL_TLS_PRIVATEKEY": "/etc/hyperledger/fabric/tls/server.key", + "ORDERER_GENERAL_TLS_CERTIFICATE": "/etc/hyperledger/fabric/tls/server.crt", + "ORDERER_GENERAL_TLS_ROOTCAS": "[/etc/hyperledger/fabric/tls/ca.crt]", + "ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE": "/etc/hyperledger/fabric/tls/server.crt", + "ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY": "/etc/hyperledger/fabric/tls/server.key", + "ORDERER_GENERAL_CLUSTER_ROOTCAS": "[/etc/hyperledger/fabric/tls/ca.crt]", "ORDERER_GENERAL_BOOTSTRAPMETHOD": "none", "ORDERER_CHANNELPARTICIPATION_ENABLED": "true", - "ORDERER_ADMIN_TLS_ENABLED": "true", "ORDERER_ADMIN_TLS_CERTIFICATE": "/etc/hyperledger/fabric/tls/server.crt", "ORDERER_ADMIN_TLS_PRIVATEKEY": "/etc/hyperledger/fabric/tls/server.key", "ORDERER_ADMIN_TLS_ROOTCAS": "[/etc/hyperledger/fabric/tls/ca.crt]", "ORDERER_ADMIN_TLS_CLIENTROOTCAS": "[/etc/hyperledger/fabric/tls/ca.crt]", "ORDERER_ADMIN_LISTENADDRESS": "0.0.0.0:7053", - "ORDERER_OPERATIONS_LISTENADDRESS": node_name+":9443", - "ORDERER_METRICS_PROVIDER": "prometheus" + "ORDERER_OPERATIONS_LISTENADDRESS": node_name + ":9443", + "ORDERER_METRICS_PROVIDER": "prometheus", } env.update(order_envs) try: # same as `docker run -dit yeasy/hyperledge-fabric:2.2.0 -e VARIABLES`` container = client.containers.run( - request.form.get('img'), - request.form.get('cmd'), - detach=True, - tty=True, - stdin_open=True, + request.form.get("img"), + request.form.get("cmd"), + detach=True, + tty=True, + stdin_open=True, network="cello-net", - name=request.form.get('name'), + name=request.form.get("name"), dns_search=["."], volumes=volumes, environment=env, - ports=port_map - ) + ports=port_map, + ) except: - res['code'] = FAIL_CODE - res['data'] = sys.exc_info()[0] - res['msg'] = 'creation failed' + res["code"] = FAIL_CODE + res["data"] = sys.exc_info()[0] + res["msg"] = "creation failed" logging.error(res) raise - res['code'] = PASS_CODE - res['data']['status'] = 'created' - res['data']['id'] = container.id - res['data']['public-grpc'] = '127.0.0.1:7050' # TODO: read the info from config file - res['data']['public-raft'] = '127.0.0.1:7052' - res['msg'] = 'node created' + res["code"] = PASS_CODE + res["data"]["status"] = "created" + res["data"]["id"] = container.id + res["data"][ + "public-grpc" + ] = "127.0.0.1:7050" # TODO: read the info from config file + res["data"]["public-raft"] = "127.0.0.1:7052" + res["msg"] = "node created" return jsonify(res) -@app.route('/api/v1/nodes/', methods=['GET', 'POST']) + +@app.route("/api/v1/nodes/", methods=["GET", "POST"]) def operate_node(id): container = client.containers.get(id) - if request.method == 'POST': - act = request.form.get('action') # only with POST + if request.method == "POST": + act = request.form.get("action") # only with POST try: - if act == 'start': + if act == "start": container.start() - res['msg'] = 'node started' - elif act == 'restart': + res["msg"] = "node started" + elif act == "restart": container.restart() - res['msg'] = 'node restarted' - elif act == 'stop': + res["msg"] = "node restarted" + elif act == "stop": container.stop() - res['msg'] = 'node stopped' - elif act == 'delete': + res["msg"] = "node stopped" + elif act == "delete": container.remove() - res['msg'] = 'node deleted' - elif act == 'update': + res["msg"] = "node deleted" + elif act == "update": env = {} - if 'msp' in request.form: - env['HLF_NODE_MSP'] = request.form.get('msp') - - if 'tls' in request.form: - env['HLF_NODE_TLS'] = request.form.get('tls') - - if 'bootstrap_block' in request.form: - env['HLF_NODE_BOOTSTRAP_BLOCK'] = request.form.get('bootstrap_block') - - if 'peer_config_file' in request.form: - env['HLF_NODE_PEER_CONFIG'] = request.form.get('peer_config_file') - - if 'orderer_config_file' in request.form: - env['HLF_NODE_ORDERER_CONFIG'] = request.form.get('orderer_config_file') - - container.exec_run(request.form.get('cmd'), detach=True, tty=True, stdin=True, environment=env) + if "msp" in request.form: + env["HLF_NODE_MSP"] = request.form.get("msp") + + if "tls" in request.form: + env["HLF_NODE_TLS"] = request.form.get("tls") + + if "bootstrap_block" in request.form: + env["HLF_NODE_BOOTSTRAP_BLOCK"] = request.form.get( + "bootstrap_block" + ) + + if "peer_config_file" in request.form: + env["HLF_NODE_PEER_CONFIG"] = request.form.get( + "peer_config_file" + ) + + if "orderer_config_file" in request.form: + env["HLF_NODE_ORDERER_CONFIG"] = request.form.get( + "orderer_config_file" + ) + + container.exec_run( + request.form.get("cmd"), + detach=True, + tty=True, + stdin=True, + environment=env, + ) container.restart() - res['msg'] = 'node updated' + res["msg"] = "node updated" else: - res['msg'] = 'undefined action' + res["msg"] = "undefined action" except: - res['code'] = FAIL_CODE - res['data'] = sys.exc_info()[0] - res['msg'] = act + 'failed' + res["code"] = FAIL_CODE + res["data"] = sys.exc_info()[0] + res["msg"] = act + "failed" logging.error(res) raise else: # GET - res['data']['status'] = container.status + res["data"]["status"] = container.status - res['code'] = PASS_CODE + res["code"] = PASS_CODE return jsonify(res) -if __name__ == '__main__': - app.run(host = "0.0.0.0", port=5001) \ No newline at end of file +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5001) diff --git a/src/agent/k8s-rest-agent/src/api/utils/exception_handler.py b/src/agent/k8s-rest-agent/src/api/utils/exception_handler.py index f24cb6701..e0e1d7c94 100644 --- a/src/agent/k8s-rest-agent/src/api/utils/exception_handler.py +++ b/src/agent/k8s-rest-agent/src/api/utils/exception_handler.py @@ -19,9 +19,9 @@ def custom_exception_handler(exc, context): ): if isinstance(exc, ValidationError): response.data["code"] = ErrorCode.ValidationError.value - response.data[ - "detail" - ] = ErrorCode.ValidationError.display_string + response.data["detail"] = ( + ErrorCode.ValidationError.display_string + ) elif isinstance(exc, ParseError): response.data["code"] = ErrorCode.ParseError.value response.data["detail"] = ErrorCode.ParseError.display_string diff --git a/src/agent/k8s-rest-agent/src/api/utils/serializers.py b/src/agent/k8s-rest-agent/src/api/utils/serializers.py index f1082c10b..832e15231 100644 --- a/src/agent/k8s-rest-agent/src/api/utils/serializers.py +++ b/src/agent/k8s-rest-agent/src/api/utils/serializers.py @@ -5,9 +5,13 @@ class PaginationSerializer(serializers.Serializer): - page = serializers.IntegerField(default=1, min_value=1, help_text="查询第几页") + page = serializers.IntegerField( + default=1, min_value=1, help_text="查询第几页" + ) per_page = serializers.IntegerField( - default=10, min_value=-1, help_text="查询分页的每页数量, 如果为-1则不限制分页数量" + default=10, + min_value=-1, + help_text="查询分页的每页数量, 如果为-1则不限制分页数量", ) limit = serializers.IntegerField( min_value=1, help_text="限制最大数量", required=False diff --git a/src/agent/k8s-rest-agent/src/server/settings.py b/src/agent/k8s-rest-agent/src/server/settings.py index 5bfbc9534..fe064797b 100644 --- a/src/agent/k8s-rest-agent/src/server/settings.py +++ b/src/agent/k8s-rest-agent/src/server/settings.py @@ -194,7 +194,10 @@ "simple": {"format": "%(levelname)s %(message)s"}, }, "handlers": { - "null": {"level": "DEBUG", "class": "logging.NullHandler",}, + "null": { + "level": "DEBUG", + "class": "logging.NullHandler", + }, "console": { "level": "DEBUG", "class": "logging.StreamHandler", @@ -202,7 +205,11 @@ }, }, "loggers": { - "django": {"handlers": ["null"], "propagate": True, "level": "INFO",}, + "django": { + "handlers": ["null"], + "propagate": True, + "level": "INFO", + }, "django.request": { "handlers": ["console"], "level": "DEBUG", diff --git a/src/agent/k8s-rest-agent/src/server/urls.py b/src/agent/k8s-rest-agent/src/server/urls.py index f741a815e..e7d0a7139 100644 --- a/src/agent/k8s-rest-agent/src/server/urls.py +++ b/src/agent/k8s-rest-agent/src/server/urls.py @@ -13,6 +13,7 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ + import os from api.routes.hello.views import HelloViewSet diff --git a/src/agent/kubernetes-agent/src/utils/client.py b/src/agent/kubernetes-agent/src/utils/client.py index 158702689..734534676 100644 --- a/src/agent/kubernetes-agent/src/utils/client.py +++ b/src/agent/kubernetes-agent/src/utils/client.py @@ -151,8 +151,10 @@ def _generate_pod_template(self, *args, **kwargs): parameters.update({"empty_dir": empty_dir}) persistent_volume_claim = volume.get("pvc", None) if persistent_volume_claim: - persistent_volume_claim = client.V1PersistentVolumeClaimVolumeSource( - claim_name=persistent_volume_claim + persistent_volume_claim = ( + client.V1PersistentVolumeClaimVolumeSource( + claim_name=persistent_volume_claim + ) ) parameters.update( {"persistent_volume_claim": persistent_volume_claim} @@ -186,10 +188,12 @@ def create_deployment(self, namespace=None, *args, **kwargs): kind="Deployment", metadata=deployment_metadata, spec=client.V1DeploymentSpec( - selector=client.V1LabelSelector(match_labels={ - "app": kwargs.get("name"), - }), - template=template_spec + selector=client.V1LabelSelector( + match_labels={ + "app": kwargs.get("name"), + } + ), + template=template_spec, ), ) diff --git a/src/api-engine/api/auth.py b/src/api-engine/api/auth.py index 8ef0f147e..86fa665a5 100644 --- a/src/api-engine/api/auth.py +++ b/src/api-engine/api/auth.py @@ -24,8 +24,7 @@ class IsAdminAuthenticated(BasePermission): def has_permission(self, request, view): return ( - request.user - and request.user.role == UserRole.Admin.name.lower() + request.user and request.user.role == UserRole.Admin.name.lower() ) diff --git a/src/api-engine/api/common/response.py b/src/api-engine/api/common/response.py index e55e2837e..0fa609dd1 100644 --- a/src/api-engine/api/common/response.py +++ b/src/api-engine/api/common/response.py @@ -12,16 +12,8 @@ def ok(data): - return { - "data": data, - "msg": None, - "status": "successful" - } + return {"data": data, "msg": None, "status": "successful"} def err(msg): - return { - "data": None, - "msg": msg, - "status": "fail" - } + return {"data": None, "msg": msg, "status": "fail"} diff --git a/src/api-engine/api/lib/agent/docker/handler.py b/src/api-engine/api/lib/agent/docker/handler.py index 7edde424b..0544fb2f8 100644 --- a/src/api-engine/api/lib/agent/docker/handler.py +++ b/src/api-engine/api/lib/agent/docker/handler.py @@ -12,11 +12,12 @@ class DockerAgent(AgentBase): """Class represents docker agent.""" + def __init__(self, node=None): """init DockerAgent - param: - node:Information needed to create, start, and delete nodes, such as organizations, nodes, and so on - return:null + param: + node:Information needed to create, start, and delete nodes, such as organizations, nodes, and so on + return:null """ if node is None: node = {} @@ -33,26 +34,33 @@ def create(self, info): :rtype: string """ try: - port_map = {str(port.internal): str(port.external) for port in info.get("ports")} + port_map = { + str(port.internal): str(port.external) + for port in info.get("ports") + } data = { - 'msp': info.get("msp")[2:-1], - 'tls': info.get("tls")[2:-1], - 'peer_config_file': info.get("config_file")[2:-1], - 'orderer_config_file': info.get("config_file")[2:-1], - 'img': 'hyperledger/fabric:2.5.10', - 'cmd': 'bash /tmp/init.sh "peer node start"' if info.get("type") == "peer" else 'bash /tmp/init.sh "orderer"', - 'name': info.get("name"), - 'type': info.get("type"), - 'port_map': port_map.__repr__(), - 'action': 'create' + "msp": info.get("msp")[2:-1], + "tls": info.get("tls")[2:-1], + "peer_config_file": info.get("config_file")[2:-1], + "orderer_config_file": info.get("config_file")[2:-1], + "img": "hyperledger/fabric:2.5.10", + "cmd": ( + 'bash /tmp/init.sh "peer node start"' + if info.get("type") == "peer" + else 'bash /tmp/init.sh "orderer"' + ), + "name": info.get("name"), + "type": info.get("type"), + "port_map": port_map.__repr__(), + "action": "create", } - response = post('{}/api/v1/nodes'.format(self._urls), data=data) + response = post("{}/api/v1/nodes".format(self._urls), data=data) if response.status_code == 200: txt = json.loads(response.text) - return txt['data']['id'] + return txt["data"]["id"] else: return None except Exception as e: @@ -61,7 +69,10 @@ def create(self, info): def delete(self, *args, **kwargs): try: - response = post('{}/api/v1/nodes/{}'.format(self._urls, self._cname), data={'action': 'delete'}) + response = post( + "{}/api/v1/nodes/{}".format(self._urls, self._cname), + data={"action": "delete"}, + ) if response.status_code == 200: return True else: @@ -72,7 +83,10 @@ def delete(self, *args, **kwargs): def start(self, *args, **kwargs): try: - response = post('{}/api/v1/nodes/{}'.format(self._urls, self._cname), data={'action': 'start'}) + response = post( + "{}/api/v1/nodes/{}".format(self._urls, self._cname), + data={"action": "start"}, + ) if response.status_code == 200: return True else: @@ -83,7 +97,10 @@ def start(self, *args, **kwargs): def restart(self, *args, **kwargs): try: - response = post('{}/api/v1/nodes/{}'.format(self._urls, self._cname), data={'action': 'restart'}) + response = post( + "{}/api/v1/nodes/{}".format(self._urls, self._cname), + data={"action": "restart"}, + ) if response.status_code == 200: return True else: @@ -94,7 +111,10 @@ def restart(self, *args, **kwargs): def stop(self, *args, **kwargs): try: - response = post('{}/api/v1/nodes/{}'.format(self._urls, self._cname), data={'action': 'stop'}) + response = post( + "{}/api/v1/nodes/{}".format(self._urls, self._cname), + data={"action": "stop"}, + ) if response.status_code == 200: return True else: @@ -105,7 +125,9 @@ def stop(self, *args, **kwargs): def get(self, *args, **kwargs): try: - response = get('{}/api/v1/nodes/{}'.format(self._urls, self._cname)) + response = get( + "{}/api/v1/nodes/{}".format(self._urls, self._cname) + ) if response.status_code == 200: return True else: @@ -118,12 +140,14 @@ def update_config(self, config_file, node_type): try: cmd = 'bash /tmp/update.sh "{} node start"'.format(node_type) data = { - 'peer_config_file': config_file, - 'orderer_config_file': config_file, - 'action': 'update', - 'cmd': cmd + "peer_config_file": config_file, + "orderer_config_file": config_file, + "action": "update", + "cmd": cmd, } - response = post('{}/api/v1/nodes/{}'.format(self._urls, self._cname), data=data) + response = post( + "{}/api/v1/nodes/{}".format(self._urls, self._cname), data=data + ) if response.status_code == 200: return True else: diff --git a/src/api-engine/api/lib/configtxgen/configtx.py b/src/api-engine/api/lib/configtxgen/configtx.py index 2e1345e27..742f83183 100644 --- a/src/api-engine/api/lib/configtxgen/configtx.py +++ b/src/api-engine/api/lib/configtxgen/configtx.py @@ -8,36 +8,52 @@ def load_configtx(filepath): - with open(filepath, 'r', encoding='utf-8') as f: + with open(filepath, "r", encoding="utf-8") as f: return yaml.load(f, Loader=yaml.FullLoader) class ConfigTX: """Class represents crypto-config yaml.""" - def __init__(self, network, filepath=CELLO_HOME, orderer=None, raft_option=None, template_path="/opt/config/configtx.yaml"): + def __init__( + self, + network, + filepath=CELLO_HOME, + orderer=None, + raft_option=None, + template_path="/opt/config/configtx.yaml", + ): """init ConfigTX - param: - network: network's name - orderer: configuration of output block - raft_option: configuration of raft - filepath: cello's working directory - return: + param: + network: network's name + orderer: configuration of output block + raft_option: configuration of raft + filepath: cello's working directory + return: """ self.filepath = filepath self.network = network self.template = load_configtx(template_path) - def create(self, name, consensus, orderers, peers, orderer_cfg=None, application=None, option=None): + def create( + self, + name, + consensus, + orderers, + peers, + orderer_cfg=None, + application=None, + option=None, + ): """create the configtx.yaml - param: - consensus:consensus - orderers:the list of orderer - peers: the list of peer - orderer_cfg: the config of orderer - application: application - option: option - return: + param: + consensus:consensus + orderers:the list of orderer + peers: the list of peer + orderer_cfg: the config of orderer + application: application + option: option + return: """ OrdererDefaults = self.template["Orderer"] ChannelDefaults = self.template["Channel"] @@ -55,42 +71,97 @@ def create(self, name, consensus, orderers, peers, orderer_cfg=None, application OrdererOrg = dict( Name="Orderer", ID=OrdererMSP, - MSPDir='{}/{}/crypto-config/ordererOrganizations/{}/msp'.format(self.filepath, orderer["name"], orderer['name'].split(".", 1)[1]), + MSPDir="{}/{}/crypto-config/ordererOrganizations/{}/msp".format( + self.filepath, + orderer["name"], + orderer["name"].split(".", 1)[1], + ), Policies=dict( - Readers=dict(Type="Signature", Rule="OR('{}.member')".format(OrdererMSP)), - Writers=dict(Type="Signature", Rule="OR('{}.member')".format(OrdererMSP)), - Admins=dict(Type="Signature", Rule="OR('{}.admin')".format(OrdererMSP)) - ) + Readers=dict( + Type="Signature", + Rule="OR('{}.member')".format(OrdererMSP), + ), + Writers=dict( + Type="Signature", + Rule="OR('{}.member')".format(OrdererMSP), + ), + Admins=dict( + Type="Signature", + Rule="OR('{}.admin')".format(OrdererMSP), + ), + ), ) - for host in orderer['hosts']: - OrdererAddress.append('{}.{}:{}'.format(host['name'], orderer['name'].split(".", 1)[1], 7050)) - Consenters.append(dict( - Host='{}.{}'.format(host['name'], orderer['name'].split(".", 1)[1]), - Port=7050, - ClientTLSCert='{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/tls/server.crt' - .format(self.filepath, orderer['name'], orderer['name'].split(".", 1)[1], host['name'], orderer['name'].split(".", 1)[1]), - ServerTLSCert='{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/tls/server.crt' - .format(self.filepath, orderer['name'], orderer['name'].split(".", 1)[1], host['name'], orderer['name'].split(".", 1)[1]))) + for host in orderer["hosts"]: + OrdererAddress.append( + "{}.{}:{}".format( + host["name"], orderer["name"].split(".", 1)[1], 7050 + ) + ) + Consenters.append( + dict( + Host="{}.{}".format( + host["name"], orderer["name"].split(".", 1)[1] + ), + Port=7050, + ClientTLSCert="{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/tls/server.crt".format( + self.filepath, + orderer["name"], + orderer["name"].split(".", 1)[1], + host["name"], + orderer["name"].split(".", 1)[1], + ), + ServerTLSCert="{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/tls/server.crt".format( + self.filepath, + orderer["name"], + orderer["name"].split(".", 1)[1], + host["name"], + orderer["name"].split(".", 1)[1], + ), + ) + ) OrdererOrg["OrdererEndpoints"] = deepcopy(OrdererAddress) OrdererOrganizations.append(OrdererOrg) PeerOrganizations = [] for peer in peers: - PeerMSP = peer['name'].split(".", 1)[0].capitalize() + "MSP" - PeerOrganizations.append(dict(Name=peer['name'].split(".", 1)[0].capitalize(), - ID=PeerMSP, - MSPDir='{}/{}/crypto-config/peerOrganizations/{}/msp'.format(self.filepath, peer['name'], peer['name']), - Policies=dict(Readers=dict(Type="Signature", Rule="OR('{}.admin', '{}.peer', '{}.client')".format(PeerMSP, PeerMSP, PeerMSP)), - Writers=dict(Type="Signature", Rule="OR('{}.admin', '{}.client')".format(PeerMSP, PeerMSP)), - Admins=dict(Type="Signature", Rule="OR('{}.admin')".format(PeerMSP)), - Endorsement=dict(Type="Signature", Rule="OR('{}.peer')".format(PeerMSP))) - )) + PeerMSP = peer["name"].split(".", 1)[0].capitalize() + "MSP" + PeerOrganizations.append( + dict( + Name=peer["name"].split(".", 1)[0].capitalize(), + ID=PeerMSP, + MSPDir="{}/{}/crypto-config/peerOrganizations/{}/msp".format( + self.filepath, peer["name"], peer["name"] + ), + Policies=dict( + Readers=dict( + Type="Signature", + Rule="OR('{}.admin', '{}.peer', '{}.client')".format( + PeerMSP, PeerMSP, PeerMSP + ), + ), + Writers=dict( + Type="Signature", + Rule="OR('{}.admin', '{}.client')".format( + PeerMSP, PeerMSP + ), + ), + Admins=dict( + Type="Signature", + Rule="OR('{}.admin')".format(PeerMSP), + ), + Endorsement=dict( + Type="Signature", + Rule="OR('{}.peer')".format(PeerMSP), + ), + ), + ) + ) Organizations = OrdererOrganizations + PeerOrganizations Capabilities = dict( Channel=ChannelCapabilities, Orderer=OrdererCapabilities, - Application=ApplicationCapabilities + Application=ApplicationCapabilities, ) Application = deepcopy(ApplicationDefaults) Orderer = deepcopy(OrdererDefaults) @@ -108,7 +179,9 @@ def create(self, name, consensus, orderers, peers, orderer_cfg=None, application Profiles[name]["Application"] = deepcopy(Application) Profiles[name]["Capabilities"] = Capabilities["Channel"] Profiles[name]["Orderer"]["Capabilities"] = Capabilities["Orderer"] - Profiles[name]["Application"]["Capabilities"] = Capabilities["Application"] + Profiles[name]["Application"]["Capabilities"] = Capabilities[ + "Application" + ] Profiles[name]["Orderer"]["Organizations"] = OrdererOrganizations Profiles[name]["Application"]["Organizations"] = PeerOrganizations @@ -118,22 +191,32 @@ def create(self, name, consensus, orderers, peers, orderer_cfg=None, application Application=Application, Orderer=Orderer, Channel=Channel, - Profiles=Profiles + Profiles=Profiles, ) - os.system('mkdir -p {}/{}'.format(self.filepath, self.network)) + os.system("mkdir -p {}/{}".format(self.filepath, self.network)) - with open('{}/{}/configtx.yaml'.format(self.filepath, self.network), 'w', encoding='utf-8') as f: + with open( + "{}/{}/configtx.yaml".format(self.filepath, self.network), + "w", + encoding="utf-8", + ) as f: yaml.dump(configtx, f, sort_keys=False) def createChannel(self, name, organizations): """create the channel.tx - param: - name: name of channel - organizations: Organizations ready to join the channel - return: + param: + name: name of channel + organizations: Organizations ready to join the channel + return: """ try: - with open('{}/{}/{}'.format(self.filepath, self.network, "configtx.yaml"), 'r+', encoding='utf-8') as f: + with open( + "{}/{}/{}".format( + self.filepath, self.network, "configtx.yaml" + ), + "r+", + encoding="utf-8", + ) as f: configtx = yaml.load(f, Loader=yaml.FullLoader) Profiles = configtx["Profiles"] Channel = configtx["Channel"] @@ -150,7 +233,13 @@ def createChannel(self, name, organizations): Profiles[name]["Orderer"] = Orderer Profiles[name]["Application"] = Application - with open('{}/{}/{}'.format(self.filepath, self.network, "configtx.yaml"), 'w', encoding='utf-8') as f: + with open( + "{}/{}/{}".format( + self.filepath, self.network, "configtx.yaml" + ), + "w", + encoding="utf-8", + ) as f: yaml.safe_dump(configtx, f, sort_keys=False) except Exception as e: @@ -159,10 +248,25 @@ def createChannel(self, name, organizations): if __name__ == "__main__": - orderers = [{"name": "org1.cello.com", "hosts": [{"name": "orderer1", "port": 8051}]}] + orderers = [ + { + "name": "org1.cello.com", + "hosts": [{"name": "orderer1", "port": 8051}], + } + ] # peers = [{"name": "org1.cello.com", "hosts": [{"name": "foo", "port": 7051},{"name": "car", "port": 7052}]}, # {"name": "org2.cello.com", "hosts": [{"name": "zoo", "port": 7053}]}] - peers = [{"name": "org1.cello.com", "hosts": [{"name": "foo", "port": 7051}, {"name": "car", "port": 7052}]}] - ConfigTX("test3").create(consensus="etcdraft", orderers=orderers, peers=peers) + peers = [ + { + "name": "org1.cello.com", + "hosts": [ + {"name": "foo", "port": 7051}, + {"name": "car", "port": 7052}, + ], + } + ] + ConfigTX("test3").create( + consensus="etcdraft", orderers=orderers, peers=peers + ) # tx = ConfigTX("test3") # print(tx.template) diff --git a/src/api-engine/api/lib/configtxgen/configtxgen.py b/src/api-engine/api/lib/configtxgen/configtxgen.py index c3341166d..d9668e0b8 100644 --- a/src/api-engine/api/lib/configtxgen/configtxgen.py +++ b/src/api-engine/api/lib/configtxgen/configtxgen.py @@ -5,20 +5,27 @@ import subprocess import logging + LOG = logging.getLogger(__name__) class ConfigTxGen: """Class represents cryptotxgen.""" - def __init__(self, network, filepath=CELLO_HOME, configtxgen=FABRIC_TOOL, version=FABRIC_VERSION): + def __init__( + self, + network, + filepath=CELLO_HOME, + configtxgen=FABRIC_TOOL, + version=FABRIC_VERSION, + ): """init CryptoGen - param: - network: network's name - configtxgen: tool path - version: version - filepath: cello's working directory - return: + param: + network: network's name + configtxgen: tool path + version: version + filepath: cello's working directory + return: """ self.network = network self.configtxgen = configtxgen + "/configtxgen" @@ -27,19 +34,23 @@ def __init__(self, network, filepath=CELLO_HOME, configtxgen=FABRIC_TOOL, versio def genesis(self, profile="", channelid="", outputblock="genesis.block"): """generate gensis - param: - profile: profile - channelid: channelid - outputblock: outputblock - return: + param: + profile: profile + channelid: channelid + outputblock: outputblock + return: """ try: command = [ self.configtxgen, - "-configPath", "{}/{}/".format(self.filepath, self.network), - "-profile", "{}".format(profile), - "-outputBlock", "{}/{}/{}".format(self.filepath, self.network, outputblock), - "-channelID", "{}".format(channelid) + "-configPath", + "{}/{}/".format(self.filepath, self.network), + "-profile", + "{}".format(profile), + "-outputBlock", + "{}/{}/{}".format(self.filepath, self.network, outputblock), + "-channelID", + "{}".format(channelid), ] LOG.info(" ".join(command)) @@ -56,10 +67,10 @@ def genesis(self, profile="", channelid="", outputblock="genesis.block"): def anchorpeer(self, profile, channelid, outputblock): """set anchorpeer - param: - profile: profile - channelid: channelid - outputblock: outputblock - return: + param: + profile: profile + channelid: channelid + outputblock: outputblock + return: """ pass diff --git a/src/api-engine/api/lib/configtxlator/configtxlator.py b/src/api-engine/api/lib/configtxlator/configtxlator.py index 9f5e1aa3a..ec444db19 100644 --- a/src/api-engine/api/lib/configtxlator/configtxlator.py +++ b/src/api-engine/api/lib/configtxlator/configtxlator.py @@ -5,6 +5,7 @@ from api.config import FABRIC_TOOL, FABRIC_VERSION import logging + LOG = logging.getLogger(__name__) @@ -27,12 +28,13 @@ def proto_encode(self, input, type, output): output: A file to write the output to. """ try: - command = [self.configtxlator, - "proto_encode", - "--input={}".format(input), - "--type={}".format(type), - "--output={}".format(output), - ] + command = [ + self.configtxlator, + "proto_encode", + "--input={}".format(input), + "--type={}".format(type), + "--output={}".format(output), + ] LOG.info(" ".join(command)) @@ -52,12 +54,13 @@ def proto_decode(self, input, type, output): config """ try: - command = [self.configtxlator, - "proto_decode", - "--type={}".format(type), - "--input={}".format(input), - "--output={}".format(output), - ] + command = [ + self.configtxlator, + "proto_decode", + "--type={}".format(type), + "--input={}".format(input), + "--output={}".format(output), + ] LOG.info(" ".join(command)) @@ -79,13 +82,14 @@ def compute_update(self, original, updated, channel_id, output): output: A file to write the JSON document to. """ try: - command = [self.configtxlator, - "compute_update", - "--original={}".format(original), - "--updated={}".format(updated), - "--channel_id={}".format(channel_id), - "--output={}".format(output), - ] + command = [ + self.configtxlator, + "compute_update", + "--original={}".format(original), + "--updated={}".format(updated), + "--channel_id={}".format(channel_id), + "--output={}".format(output), + ] LOG.info(" ".join(command)) diff --git a/src/api-engine/api/lib/peer/chaincode.py b/src/api-engine/api/lib/peer/chaincode.py index c03f6a16a..f5ab6ca64 100644 --- a/src/api-engine/api/lib/peer/chaincode.py +++ b/src/api-engine/api/lib/peer/chaincode.py @@ -27,8 +27,11 @@ def lifecycle_package(self, cc_name, cc_version, cc_path, language): """ try: label = cc_name + "_" + cc_version - res = os.system("{} lifecycle chaincode package {}.tar.gz --path {} --lang {} --label {}" - .format(self.peer, cc_name, cc_path, language, label)) + res = os.system( + "{} lifecycle chaincode package {}.tar.gz --path {} --lang {} --label {}".format( + self.peer, cc_name, cc_path, language, label + ) + ) res = res >> 8 except Exception as e: err_msg = "package chaincode failed for {}!".format(e) @@ -44,8 +47,10 @@ def lifecycle_install(self, cc_targz): try: command = [ self.peer, - "lifecycle", "chaincode", "install", - cc_targz + "lifecycle", + "chaincode", + "install", + cc_targz, ] LOG.info(" ".join(command)) res = os.system(" ".join(command)) @@ -66,16 +71,20 @@ def lifecycle_query_installed(self, timeout): try: command = [ self.peer, - "lifecycle", "chaincode", "queryinstalled", - "--output", "json", - "--connTimeout", timeout + "lifecycle", + "chaincode", + "queryinstalled", + "--output", + "json", + "--connTimeout", + timeout, ] LOG.info(" ".join(command)) res = subprocess.Popen( command, shell=False, stdout=subprocess.PIPE, - stderr=subprocess.PIPE + stderr=subprocess.PIPE, ) stdout, stderr = res.communicate() @@ -103,10 +112,13 @@ def lifecycle_get_installed_package(self, timeout): res, installed = self.lifecycle_query_installed("3s") res_return = 0 if res == 0: - for item in installed['installed_chaincodes']: - res_get = os.system("{} lifecycle chaincode getinstalledpackage --package-id {} " - "--output-directory {} --connTimeout {}".format(self.peer, - item['package_id'], FABRIC_CFG, timeout)) + for item in installed["installed_chaincodes"]: + res_get = os.system( + "{} lifecycle chaincode getinstalledpackage --package-id {} " + "--output-directory {} --connTimeout {}".format( + self.peer, item["package_id"], FABRIC_CFG, timeout + ) + ) res_get = res_get >> 8 res_return = res_return or res_get else: @@ -117,8 +129,16 @@ def lifecycle_get_installed_package(self, timeout): raise Exception(err_msg) return res_return - def lifecycle_approve_for_my_org(self, orderer_url, channel_name, cc_name, - chaincode_version, sequence, policy, init_flag): + def lifecycle_approve_for_my_org( + self, + orderer_url, + channel_name, + cc_name, + chaincode_version, + sequence, + policy, + init_flag, + ): """ The administrator can use the peer lifecycle chaincode approveformyorg subcommand to approve the chain code on behalf of the organization. @@ -135,39 +155,63 @@ def lifecycle_approve_for_my_org(self, orderer_url, channel_name, cc_name, res, installed = self.lifecycle_query_installed("3s") cc_label = cc_name + "_" + chaincode_version package_id = "" - for each in installed['installed_chaincodes']: - if each['label'] == cc_label: - package_id = each['package_id'] + for each in installed["installed_chaincodes"]: + if each["label"] == cc_label: + package_id = each["package_id"] break if package_id == "": - return 1, "not exist the chaincode, please check chaincode_name and chaincode_version" + return ( + 1, + "not exist the chaincode, please check chaincode_name and chaincode_version", + ) command = [] - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): command = [ self.peer, - "lifecycle", "chaincode", "approveformyorg", - "-o", orderer_url, - "--channelID", channel_name, - "--name", cc_name, - "--version", chaincode_version, - "--package-id", package_id, - "--sequence", str(sequence) + "lifecycle", + "chaincode", + "approveformyorg", + "-o", + orderer_url, + "--channelID", + channel_name, + "--name", + cc_name, + "--version", + chaincode_version, + "--package-id", + package_id, + "--sequence", + str(sequence), ] else: ORDERER_CA = os.getenv("ORDERER_CA") command = [ self.peer, - "lifecycle", "chaincode", "approveformyorg", - "-o", orderer_url, - "--ordererTLSHostnameOverride", orderer_url.split(":")[0], - "--channelID", channel_name, - "--name", cc_name, - "--version", chaincode_version, - "--package-id", package_id, - "--sequence", str(sequence), + "lifecycle", + "chaincode", + "approveformyorg", + "-o", + orderer_url, + "--ordererTLSHostnameOverride", + orderer_url.split(":")[0], + "--channelID", + channel_name, + "--name", + cc_name, + "--version", + chaincode_version, + "--package-id", + package_id, + "--sequence", + str(sequence), "--tls", - "--cafile", ORDERER_CA + "--cafile", + ORDERER_CA, ] if init_flag: @@ -177,8 +221,12 @@ def lifecycle_approve_for_my_org(self, orderer_url, channel_name, cc_name, command.append(policy) LOG.info(" ".join(command)) - res = subprocess.Popen(command, shell=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + command, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode @@ -201,10 +249,13 @@ def lifecycle_query_approved(self, channel_name, cc_name): """ try: - res = subprocess.Popen("{} lifecycle chaincode queryapproved --output json --channelID {}" - " --name {}".format(self.peer, - channel_name, cc_name), - shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + "{} lifecycle chaincode queryapproved --output json --channelID {}" + " --name {}".format(self.peer, channel_name, cc_name), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode if return_code == 0: @@ -219,7 +270,9 @@ def lifecycle_query_approved(self, channel_name, cc_name): return return_code, chaincodes_info - def lifecycle_check_commit_readiness(self, channel_name, cc_name, cc_version, sequence=1): + def lifecycle_check_commit_readiness( + self, channel_name, cc_name, cc_version, sequence=1 + ): """ :param channel_name:channel name :param cc_name: chaincode name @@ -230,33 +283,55 @@ def lifecycle_check_commit_readiness(self, channel_name, cc_name, cc_version, se try: ORDERER_CA = os.getenv("ORDERER_CA") command = [] - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): command = [ self.peer, - "lifecycle", "chaincode", "checkcommitreadiness", - "--channelID", channel_name, - "--name", cc_name, - "--version", cc_version, - "--sequence", str(sequence), - "--output", "json", + "lifecycle", + "chaincode", + "checkcommitreadiness", + "--channelID", + channel_name, + "--name", + cc_name, + "--version", + cc_version, + "--sequence", + str(sequence), + "--output", + "json", ] else: command = [ self.peer, - "lifecycle", "chaincode", "checkcommitreadiness", - "--channelID", channel_name, - "--name", cc_name, - "--version", cc_version, - "--sequence", str(sequence), + "lifecycle", + "chaincode", + "checkcommitreadiness", + "--channelID", + channel_name, + "--name", + cc_name, + "--version", + cc_version, + "--sequence", + str(sequence), "--tls", - "--cafile", ORDERER_CA, - "--output", "json", + "--cafile", + ORDERER_CA, + "--output", + "json", ] LOG.info(" ".join(command)) - res = subprocess.Popen(command, shell=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + command, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode if return_code == 0: @@ -267,10 +342,23 @@ def lifecycle_check_commit_readiness(self, channel_name, cc_name, cc_version, se stderr = str(stderr, encoding="utf-8") return return_code, stderr except Exception as e: - err_msg = "lifecycle_check_commit_readiness failed for {}!".format(e) + err_msg = "lifecycle_check_commit_readiness failed for {}!".format( + e + ) raise Exception(err_msg) - def lifecycle_commit(self, orderer_url, channel_name, cc_name, chaincode_version, sequence, policy, peer_list=[], peer_root_certs=[], init_flag=False): + def lifecycle_commit( + self, + orderer_url, + channel_name, + cc_name, + chaincode_version, + sequence, + policy, + peer_list=[], + peer_root_certs=[], + init_flag=False, + ): """ The administrator can submit the chain code definition to the specified channel by using the peer lifecycle chain code commit subcommand @@ -287,29 +375,48 @@ def lifecycle_commit(self, orderer_url, channel_name, cc_name, chaincode_version """ try: command = [] - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): command = [ self.peer, - "lifecycle", "chaincode", "commit", - "-o", orderer_url, - "--channelID", channel_name, - "--name", cc_name, - "--version", chaincode_version, - "--sequence", str(sequence), + "lifecycle", + "chaincode", + "commit", + "-o", + orderer_url, + "--channelID", + channel_name, + "--name", + cc_name, + "--version", + chaincode_version, + "--sequence", + str(sequence), ] else: ORDERER_CA = os.getenv("ORDERER_CA") command = [ self.peer, - "lifecycle", "chaincode", "commit", - "-o", orderer_url, - "--ordererTLSHostnameOverride", orderer_url.split(":")[0], - "--channelID", channel_name, - "--name", cc_name, - "--version", chaincode_version, - "--sequence", str(sequence), + "lifecycle", + "chaincode", + "commit", + "-o", + orderer_url, + "--ordererTLSHostnameOverride", + orderer_url.split(":")[0], + "--channelID", + channel_name, + "--name", + cc_name, + "--version", + chaincode_version, + "--sequence", + str(sequence), "--tls", - "--cafile", ORDERER_CA, + "--cafile", + ORDERER_CA, ] for i in range(len(peer_list)): @@ -343,14 +450,23 @@ def lifecycle_query_committed(self, channel_name, cc_name): try: command = [ self.peer, - "lifecycle", "chaincode", "querycommitted", - "--channelID", channel_name, - "--output", "json", - "--name", cc_name, + "lifecycle", + "chaincode", + "querycommitted", + "--channelID", + channel_name, + "--output", + "json", + "--name", + cc_name, ] LOG.info(" ".join(command)) - res = subprocess.Popen(command, shell=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + command, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode if return_code == 0: @@ -364,7 +480,15 @@ def lifecycle_query_committed(self, channel_name, cc_name): err_msg = "lifecycle_query_committed failed for {}!".format(e) raise Exception(err_msg) - def invoke(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, args, init=False): + def invoke( + self, + orderer_url, + orderer_tls_rootcert, + channel_name, + cc_name, + args, + init=False, + ): """ :param orderer_url:orderer accessable url :param orderer_tls_rootcert: orderer tls certificate @@ -384,24 +508,43 @@ def invoke(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, args, invoke_command = "{} chaincode invoke -o {} --channelID {} --name {} -c '{}'" invoke_command_tls = "{} chaincode invoke -o {} --tls --cafile {} --channelID {} --name {} -c '{}'" - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: - res = subprocess.Popen(invoke_command.format(self.peer, orderer_url, channel_name, cc_name, args), - shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): + res = subprocess.Popen( + invoke_command.format( + self.peer, orderer_url, channel_name, cc_name, args + ), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) _, stderr = res.communicate() return_code = res.returncode if return_code == 0: - return return_code, '' + return return_code, "" else: stderr = str(stderr, encoding="utf-8") return return_code, stderr else: - res = subprocess.Popen(invoke_command_tls.format(self.peer, orderer_url, orderer_tls_rootcert, - channel_name, cc_name, args), - shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + invoke_command_tls.format( + self.peer, + orderer_url, + orderer_tls_rootcert, + channel_name, + cc_name, + args, + ), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) _, stderr = res.communicate() return_code = res.returncode if return_code == 0: - return return_code, '' + return return_code, "" else: stderr = str(stderr, encoding="utf-8") return return_code, stderr @@ -409,24 +552,44 @@ def invoke(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, args, err_msg = "invoke failed for {}!".format(e) raise Exception(err_msg) - def query(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, args): + def query( + self, orderer_url, orderer_tls_rootcert, channel_name, cc_name, args + ): try: - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: - res = subprocess.Popen("{} chaincode query -o {} --channelID {} --name {} -c '{}'" - .format(self.peer, orderer_url, channel_name, cc_name, args), - shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): + res = subprocess.Popen( + "{} chaincode query -o {} --channelID {} --name {} -c '{}'".format( + self.peer, orderer_url, channel_name, cc_name, args + ), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode if return_code == 0: - return return_code, '' + return return_code, "" else: stderr = str(stderr, encoding="utf-8") return return_code, stderr else: - res = subprocess.Popen("{} chaincode query -o {} --tls --cafile {} --channelID {}" - " --name {} -c '{}'".format(self.peer, orderer_url, orderer_tls_rootcert, - channel_name, cc_name, args), - shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + "{} chaincode query -o {} --tls --cafile {} --channelID {}" + " --name {} -c '{}'".format( + self.peer, + orderer_url, + orderer_tls_rootcert, + channel_name, + cc_name, + args, + ), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode if return_code == 0: @@ -448,10 +611,12 @@ def lifecycle_calculatepackageid(self, cc_path): """ try: res = subprocess.Popen( - "{} lifecycle chaincode calculatepackageid {} ".format(self.peer, cc_path), + "{} lifecycle chaincode calculatepackageid {} ".format( + self.peer, cc_path + ), shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE + stderr=subprocess.PIPE, ) stdout, stderr = res.communicate() return_code = res.returncode diff --git a/src/api-engine/api/lib/peer/channel.py b/src/api-engine/api/lib/peer/channel.py index abba3d83e..b6acbb5bf 100644 --- a/src/api-engine/api/lib/peer/channel.py +++ b/src/api-engine/api/lib/peer/channel.py @@ -24,27 +24,45 @@ def create(self, channel, orderer_admin_url, block_path, time_out="90s"): try: command = [] - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): command = [ self.osnadmin, - "channel", "join", - "--channelID", channel, - "--config-block", block_path, - "-o", orderer_admin_url, + "channel", + "join", + "--channelID", + channel, + "--config-block", + block_path, + "-o", + orderer_admin_url, ] else: ORDERER_CA = os.getenv("ORDERER_CA") - ORDERER_ADMIN_TLS_SIGN_CERT = os.getenv("ORDERER_ADMIN_TLS_SIGN_CERT") - ORDERER_ADMIN_TLS_PRIVATE_KEY = os.getenv("ORDERER_ADMIN_TLS_PRIVATE_KEY") + ORDERER_ADMIN_TLS_SIGN_CERT = os.getenv( + "ORDERER_ADMIN_TLS_SIGN_CERT" + ) + ORDERER_ADMIN_TLS_PRIVATE_KEY = os.getenv( + "ORDERER_ADMIN_TLS_PRIVATE_KEY" + ) command = [ self.osnadmin, - "channel", "join", - "--channelID", channel, - "--config-block", block_path, - "-o", orderer_admin_url, - "--ca-file", ORDERER_CA, - "--client-cert", ORDERER_ADMIN_TLS_SIGN_CERT, - "--client-key", ORDERER_ADMIN_TLS_PRIVATE_KEY + "channel", + "join", + "--channelID", + channel, + "--config-block", + block_path, + "-o", + orderer_admin_url, + "--ca-file", + ORDERER_CA, + "--client-cert", + ORDERER_ADMIN_TLS_SIGN_CERT, + "--client-key", + ORDERER_ADMIN_TLS_PRIVATE_KEY, ] LOG.info(" ".join(command)) @@ -62,8 +80,12 @@ def create(self, channel, orderer_admin_url, block_path, time_out="90s"): def list(self): try: - res = subprocess.Popen("{} channel list".format(self.peer), shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + "{} channel list".format(self.peer), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode @@ -92,13 +114,19 @@ def update(self, channel, channel_tx, orderer_url): command = [ self.peer, - "channel", "update", - "-f", channel_tx, - "-c", channel, - "-o", orderer_url, - "--ordererTLSHostnameOverride", orderer_url.split(":")[0], + "channel", + "update", + "-f", + channel_tx, + "-c", + channel, + "-o", + orderer_url, + "--ordererTLSHostnameOverride", + orderer_url.split(":")[0], "--tls", - "--cafile", ORDERER_CA + "--cafile", + ORDERER_CA, ] LOG.info(" ".join(command)) @@ -109,7 +137,14 @@ def update(self, channel, channel_tx, orderer_url): raise Exception(err_msg) return res - def fetch(self, block_path, channel, orderer_general_url, max_retries=5, retry_interval=1): + def fetch( + self, + block_path, + channel, + orderer_general_url, + max_retries=5, + retry_interval=1, + ): """ Fetch a specified block, writing it to a file e.g. .block. params: @@ -118,26 +153,39 @@ def fetch(self, block_path, channel, orderer_general_url, max_retries=5, retry_i """ res = 0 command = [] - if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None: + if ( + os.getenv("CORE_PEER_TLS_ENABLED") == "false" + or os.getenv("CORE_PEER_TLS_ENABLED") is None + ): command = [ self.peer, - "channel", "fetch", - "config", block_path, - "-o", orderer_general_url, - "-c", channel + "channel", + "fetch", + "config", + block_path, + "-o", + orderer_general_url, + "-c", + channel, ] else: ORDERER_CA = os.getenv("ORDERER_CA") orderer_address = orderer_general_url.split(":")[0] command = [ self.peer, - "channel", "fetch", - "config", block_path, - "-o", orderer_general_url, - "--ordererTLSHostnameOverride", orderer_address, - "-c", channel, + "channel", + "fetch", + "config", + block_path, + "-o", + orderer_general_url, + "--ordererTLSHostnameOverride", + orderer_address, + "-c", + channel, "--tls", - "--cafile", ORDERER_CA + "--cafile", + ORDERER_CA, ] LOG.info(" ".join(command)) @@ -158,7 +206,9 @@ def fetch(self, block_path, channel, orderer_general_url, max_retries=5, retry_i if attempt <= max_retries: time.sleep(retry_interval) else: - LOG.error(f"Failed to fetch block after {max_retries} attempts") + LOG.error( + f"Failed to fetch block after {max_retries} attempts" + ) raise e return res @@ -171,7 +221,8 @@ def signconfigtx(self, channel_tx): """ try: res = os.system( - "{} channel signconfigtx -f {}".format(self.peer, channel_tx)) + "{} channel signconfigtx -f {}".format(self.peer, channel_tx) + ) except Exception as e: err_msg = "signs a configtx update failed {}".format(e) raise Exception(err_msg) @@ -204,8 +255,12 @@ def getinfo(self, channel): channel: In case of a newChain command, the channel ID to create. """ try: - res = subprocess.Popen("{} channel getinfo -c {}".format(self.peer, channel), shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + res = subprocess.Popen( + "{} channel getinfo -c {}".format(self.peer, channel), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = res.communicate() return_code = res.returncode @@ -220,6 +275,7 @@ def getinfo(self, channel): return return_code, stderr except Exception as e: err_msg = "get blockchain information of a specified channel failed. {}".format( - e) + e + ) raise Exception(err_msg) return return_code, body diff --git a/src/api-engine/api/lib/pki/cryptogen/cryptocfg.py b/src/api-engine/api/lib/pki/cryptogen/cryptocfg.py index c9eff0dcd..25ba0e383 100644 --- a/src/api-engine/api/lib/pki/cryptogen/cryptocfg.py +++ b/src/api-engine/api/lib/pki/cryptogen/cryptocfg.py @@ -9,17 +9,26 @@ class CryptoConfig: """Class represents crypto-config yaml.""" - def __init__(self, name, file="crypto-config.yaml", country="CN", locality="BJ", province="CP", enablenodeous=True, filepath=CELLO_HOME): + def __init__( + self, + name, + file="crypto-config.yaml", + country="CN", + locality="BJ", + province="CP", + enablenodeous=True, + filepath=CELLO_HOME, + ): """init CryptoConfig - param: - name: organization's name - file: crypto-config.yaml - country: country - locality: locality - province: province - enablenodeous: enablenodeous - filepath: cello's working directory - return: + param: + name: organization's name + file: crypto-config.yaml + country: country + locality: locality + province: province + enablenodeous: enablenodeous + filepath: cello's working directory + return: """ self.filepath = filepath self.name = name @@ -31,16 +40,18 @@ def __init__(self, name, file="crypto-config.yaml", country="CN", locality="BJ", def create(self, peernum, orderernum) -> None: """create the crypto-config.yaml - param - return: + param + return: """ try: network = {} for item in ["Peer", "Orderer"]: org = [] - ca = dict(Country=self.country, - Locality=self.locality, - Province=self.province) + ca = dict( + Country=self.country, + Locality=self.locality, + Province=self.province, + ) specs = [] # for host in org_info["Specs"]: # specs.append(dict(Hostname=host)) @@ -48,27 +59,39 @@ def create(self, peernum, orderernum) -> None: if item == "Peer": template = dict(Count=peernum) users = dict(Count=1) - org.append(dict(Domain=self.name, - Name=self.name.split(".")[0].capitalize(), - CA=ca, - Specs=specs, - EnableNodeOUs=self.enablenodeous, - Template=template, - Users=users)) - network = {'PeerOrgs': org} + org.append( + dict( + Domain=self.name, + Name=self.name.split(".")[0].capitalize(), + CA=ca, + Specs=specs, + EnableNodeOUs=self.enablenodeous, + Template=template, + Users=users, + ) + ) + network = {"PeerOrgs": org} else: template = dict(Count=orderernum) - org.append(dict(Domain=self.name.split(".", 1)[1], - Name=item, - CA=ca, - Specs=specs, - EnableNodeOUs=self.enablenodeous, - Template=template)) - network['OrdererOrgs'] = org + org.append( + dict( + Domain=self.name.split(".", 1)[1], + Name=item, + CA=ca, + Specs=specs, + EnableNodeOUs=self.enablenodeous, + Template=template, + ) + ) + network["OrdererOrgs"] = org - os.system('mkdir -p {}/{}'.format(self.filepath, self.name)) + os.system("mkdir -p {}/{}".format(self.filepath, self.name)) - with open('{}/{}/{}'.format(self.filepath, self.name, self.file), 'w', encoding='utf-8') as f: + with open( + "{}/{}/{}".format(self.filepath, self.name, self.file), + "w", + encoding="utf-8", + ) as f: yaml.dump(network, f) except Exception as e: err_msg = "CryptoConfig create failed for {}!".format(e) @@ -76,17 +99,21 @@ def create(self, peernum, orderernum) -> None: def update(self, org_info: any) -> None: """update the crypto-config.yaml - param: - org_info: Node of type peer or orderer - return: + param: + org_info: Node of type peer or orderer + return: """ try: - with open('{}/{}/{}'.format(self.filepath, self.name, self.file), 'r+', encoding='utf-8') as f: + with open( + "{}/{}/{}".format(self.filepath, self.name, self.file), + "r+", + encoding="utf-8", + ) as f: network = yaml.load(f, Loader=yaml.FullLoader) if org_info["type"] == "peer": - orgs = network['PeerOrgs'] + orgs = network["PeerOrgs"] else: - orgs = network['OrdererOrgs'] + orgs = network["OrdererOrgs"] for org in orgs: # org["Template"]["Count"] += 1 @@ -94,7 +121,11 @@ def update(self, org_info: any) -> None: for host in org_info["Specs"]: specs.append(dict(Hostname=host)) - with open('{}/{}/{}'.format(self.filepath, self.name, self.file), 'w', encoding='utf-8') as f: + with open( + "{}/{}/{}".format(self.filepath, self.name, self.file), + "w", + encoding="utf-8", + ) as f: yaml.dump(network, f) except Exception as e: err_msg = "CryptoConfig update failed for {}!".format(e) @@ -102,11 +133,11 @@ def update(self, org_info: any) -> None: def delete(self): """delete the crypto-config.yaml - param: - return: + param: + return: """ try: - os.system('rm -rf {}/{}'.format(self.filepath, self.name)) + os.system("rm -rf {}/{}".format(self.filepath, self.name)) except Exception as e: err_msg = "CryptoConfig delete failed for {}!".format(e) raise Exception(err_msg) diff --git a/src/api-engine/api/lib/pki/cryptogen/cryptogen.py b/src/api-engine/api/lib/pki/cryptogen/cryptogen.py index bad3fb466..96c0fad00 100644 --- a/src/api-engine/api/lib/pki/cryptogen/cryptogen.py +++ b/src/api-engine/api/lib/pki/cryptogen/cryptogen.py @@ -5,20 +5,27 @@ from api.config import CELLO_HOME, FABRIC_TOOL, FABRIC_VERSION import logging + LOG = logging.getLogger(__name__) class CryptoGen: """Class represents crypto-config tool.""" - def __init__(self, name, filepath=CELLO_HOME, cryptogen=FABRIC_TOOL, version=FABRIC_VERSION): + def __init__( + self, + name, + filepath=CELLO_HOME, + cryptogen=FABRIC_TOOL, + version=FABRIC_VERSION, + ): """init CryptoGen - param: - name: organization's name - cryptogen: tool path - version: version - filepath: cello's working directory - return: + param: + name: organization's name + cryptogen: tool path + version: version + filepath: cello's working directory + return: """ self.cryptogen = cryptogen + "/cryptogen" self.filepath = filepath @@ -27,17 +34,17 @@ def __init__(self, name, filepath=CELLO_HOME, cryptogen=FABRIC_TOOL, version=FAB def generate(self, output="crypto-config", config="crypto-config.yaml"): """Generate key material - param: - output: The output directory in which to place artifacts - config: The configuration template to use - return: + param: + output: The output directory in which to place artifacts + config: The configuration template to use + return: """ try: command = [ self.cryptogen, "generate", "--output={}/{}/{}".format(self.filepath, self.name, output), - "--config={}/{}/{}".format(self.filepath, self.name, config) + "--config={}/{}/{}".format(self.filepath, self.name, config), ] LOG.info(" ".join(command)) @@ -50,17 +57,17 @@ def generate(self, output="crypto-config", config="crypto-config.yaml"): def extend(self, input="crypto-config", config="crypto-config.yaml"): """Extend existing network - param: - input: The input directory in which existing network place - config: The configuration template to use - return: + param: + input: The input directory in which existing network place + config: The configuration template to use + return: """ try: command = [ self.cryptogen, "extend", "--input={}/{}/{}".format(self.filepath, self.name, input), - "--config={}/{}/{}".format(self.filepath, self.name, config) + "--config={}/{}/{}".format(self.filepath, self.name, config), ] LOG.info(" ".join(command)) diff --git a/src/api-engine/api/migrations/0001_initial.py b/src/api-engine/api/migrations/0001_initial.py index 8bb6c3739..fc151d931 100644 --- a/src/api-engine/api/migrations/0001_initial.py +++ b/src/api-engine/api/migrations/0001_initial.py @@ -16,271 +16,1147 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), + ("auth", "0012_alter_user_first_name_max_length"), ] operations = [ migrations.CreateModel( - name='UserProfile', + name="UserProfile", fields=[ - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of user', primary_key=True, serialize=False)), - ('email', models.EmailField(db_index=True, max_length=254, unique=True)), - ('username', models.CharField(default='', help_text='Name of user', max_length=64)), - ('role', models.CharField(choices=[('admin', 'Admin'), ('operator', 'Operator'), ('user', 'User')], default=2, max_length=64)), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ( + "password", + models.CharField(max_length=128, verbose_name="password"), + ), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "first_name", + models.CharField( + blank=True, max_length=150, verbose_name="first name" + ), + ), + ( + "last_name", + models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, + verbose_name="date joined", + ), + ), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of user", + primary_key=True, + serialize=False, + ), + ), + ( + "email", + models.EmailField( + db_index=True, max_length=254, unique=True + ), + ), + ( + "username", + models.CharField( + default="", help_text="Name of user", max_length=64 + ), + ), + ( + "role", + models.CharField( + choices=[ + ("admin", "Admin"), + ("operator", "Operator"), + ("user", "User"), + ], + default=2, + max_length=64, + ), + ), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), ], options={ - 'verbose_name': 'User Info', - 'verbose_name_plural': 'User Info', - 'ordering': ['-date_joined'], + "verbose_name": "User Info", + "verbose_name_plural": "User Info", + "ordering": ["-date_joined"], }, managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ("objects", django.contrib.auth.models.UserManager()), ], ), migrations.CreateModel( - name='Agent', + name="Agent", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of agent', primary_key=True, serialize=False)), - ('name', models.CharField(default='agent-0d4db641fedc458fa54e9f364e411698', help_text='Agent name, can be generated automatically.', max_length=64)), - ('urls', models.URLField(blank=True, help_text='Agent URL', null=True)), - ('status', models.CharField(choices=[('inactive', 'Inactive'), ('active', 'Active')], default='active', help_text='Status of agent', max_length=10)), - ('type', models.CharField(choices=[('docker', 'Docker'), ('kubernetes', 'Kubernetes')], default='docker', help_text='Type of agent', max_length=32)), - ('config_file', models.FileField(blank=True, help_text='Config file for agent', max_length=256, upload_to=api.models.get_agent_config_file_path)), - ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create time of agent')), - ('free_ports', django.contrib.postgres.fields.ArrayField(base_field=models.IntegerField(blank=True), help_text='Agent free ports.', null=True, size=None)), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of agent", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="agent-0d4db641fedc458fa54e9f364e411698", + help_text="Agent name, can be generated automatically.", + max_length=64, + ), + ), + ( + "urls", + models.URLField( + blank=True, help_text="Agent URL", null=True + ), + ), + ( + "status", + models.CharField( + choices=[ + ("inactive", "Inactive"), + ("active", "Active"), + ], + default="active", + help_text="Status of agent", + max_length=10, + ), + ), + ( + "type", + models.CharField( + choices=[ + ("docker", "Docker"), + ("kubernetes", "Kubernetes"), + ], + default="docker", + help_text="Type of agent", + max_length=32, + ), + ), + ( + "config_file", + models.FileField( + blank=True, + help_text="Config file for agent", + max_length=256, + upload_to=api.models.get_agent_config_file_path, + ), + ), + ( + "created_at", + models.DateTimeField( + auto_now_add=True, help_text="Create time of agent" + ), + ), + ( + "free_ports", + django.contrib.postgres.fields.ArrayField( + base_field=models.IntegerField(blank=True), + help_text="Agent free ports.", + null=True, + size=None, + ), + ), ], options={ - 'ordering': ('-created_at',), + "ordering": ("-created_at",), }, ), migrations.CreateModel( - name='ChainCode', + name="ChainCode", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, editable=False, help_text='ID of ChainCode', primary_key=True, serialize=False, unique=True)), - ('package_id', models.CharField(editable=False, help_text='package_id of chainCode', max_length=128, unique=True)), - ('label', models.CharField(help_text='label of chainCode', max_length=128)), - ('creator', models.CharField(help_text='creator of chainCode', max_length=128)), - ('language', models.CharField(help_text='language of chainCode', max_length=128)), - ('description', models.CharField(blank=True, help_text='description of chainCode', max_length=128, null=True)), - ('create_ts', models.DateTimeField(auto_now_add=True, help_text='Create time of chainCode')), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + editable=False, + help_text="ID of ChainCode", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "package_id", + models.CharField( + editable=False, + help_text="package_id of chainCode", + max_length=128, + unique=True, + ), + ), + ( + "label", + models.CharField( + help_text="label of chainCode", max_length=128 + ), + ), + ( + "creator", + models.CharField( + help_text="creator of chainCode", max_length=128 + ), + ), + ( + "language", + models.CharField( + help_text="language of chainCode", max_length=128 + ), + ), + ( + "description", + models.CharField( + blank=True, + help_text="description of chainCode", + max_length=128, + null=True, + ), + ), + ( + "create_ts", + models.DateTimeField( + auto_now_add=True, help_text="Create time of chainCode" + ), + ), ], ), migrations.CreateModel( - name='FabricCA', + name="FabricCA", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('admin_name', models.CharField(default='admin', help_text='Admin username for ca server', max_length=32)), - ('admin_password', models.CharField(default='adminpw', help_text='Admin password for ca server', max_length=32)), - ('hosts', models.JSONField(blank=True, default=list, help_text='Hosts for ca', null=True)), - ('type', models.CharField(choices=[('tls', 'TLS'), ('signature', 'Signature')], default='signature', help_text='Fabric ca server type', max_length=32)), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "admin_name", + models.CharField( + default="admin", + help_text="Admin username for ca server", + max_length=32, + ), + ), + ( + "admin_password", + models.CharField( + default="adminpw", + help_text="Admin password for ca server", + max_length=32, + ), + ), + ( + "hosts", + models.JSONField( + blank=True, + default=list, + help_text="Hosts for ca", + null=True, + ), + ), + ( + "type", + models.CharField( + choices=[("tls", "TLS"), ("signature", "Signature")], + default="signature", + help_text="Fabric ca server type", + max_length=32, + ), + ), ], ), migrations.CreateModel( - name='FabricPeer', + name="FabricPeer", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(default='', help_text='Name of peer node', max_length=64)), - ('gossip_use_leader_reflection', models.BooleanField(default=True, help_text='Gossip use leader reflection')), - ('gossip_org_leader', models.BooleanField(default=False, help_text='Gossip org leader')), - ('gossip_skip_handshake', models.BooleanField(default=True, help_text='Gossip skip handshake')), - ('local_msp_id', models.CharField(default='', help_text='Local msp id of peer node', max_length=64)), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "name", + models.CharField( + default="", + help_text="Name of peer node", + max_length=64, + ), + ), + ( + "gossip_use_leader_reflection", + models.BooleanField( + default=True, help_text="Gossip use leader reflection" + ), + ), + ( + "gossip_org_leader", + models.BooleanField( + default=False, help_text="Gossip org leader" + ), + ), + ( + "gossip_skip_handshake", + models.BooleanField( + default=True, help_text="Gossip skip handshake" + ), + ), + ( + "local_msp_id", + models.CharField( + default="", + help_text="Local msp id of peer node", + max_length=64, + ), + ), ], ), migrations.CreateModel( - name='Govern', + name="Govern", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of govern', primary_key=True, serialize=False)), - ('name', models.CharField(default='', help_text='Name of govern', max_length=64)), - ('created_at', models.DateTimeField(auto_now_add=True)), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of govern", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="", help_text="Name of govern", max_length=64 + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), ], ), migrations.CreateModel( - name='Network', + name="Network", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of network', primary_key=True, serialize=False)), - ('name', models.CharField(default='netowrk-30858a0cf2f54ab7a5e16a94958758b5', help_text='network name, can be generated automatically.', max_length=64)), - ('type', models.CharField(default='fabric', help_text="Type of network, ['fabric']", max_length=64)), - ('version', models.CharField(default='', help_text="\n Version of network.\n Fabric supported versions: ['1.4.2', '1.5']\n ", max_length=64)), - ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create time of network')), - ('consensus', models.CharField(default='raft', help_text='Consensus of network', max_length=128)), - ('genesisblock', models.TextField(help_text='genesis block', null=True)), - ('database', models.CharField(default='leveldb', help_text='database of network', max_length=128)), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of network", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="netowrk-30858a0cf2f54ab7a5e16a94958758b5", + help_text="network name, can be generated automatically.", + max_length=64, + ), + ), + ( + "type", + models.CharField( + default="fabric", + help_text="Type of network, ['fabric']", + max_length=64, + ), + ), + ( + "version", + models.CharField( + default="", + help_text="\n Version of network.\n Fabric supported versions: ['1.4.2', '1.5']\n ", + max_length=64, + ), + ), + ( + "created_at", + models.DateTimeField( + auto_now_add=True, help_text="Create time of network" + ), + ), + ( + "consensus", + models.CharField( + default="raft", + help_text="Consensus of network", + max_length=128, + ), + ), + ( + "genesisblock", + models.TextField(help_text="genesis block", null=True), + ), + ( + "database", + models.CharField( + default="leveldb", + help_text="database of network", + max_length=128, + ), + ), ], options={ - 'ordering': ('-created_at',), + "ordering": ("-created_at",), }, ), migrations.CreateModel( - name='Node', + name="Node", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of node', primary_key=True, serialize=False)), - ('name', models.CharField(default='', help_text='Node name', max_length=64)), - ('type', models.CharField(help_text="\n Node type defined for network.\n Fabric available types: ['ca', 'orderer', 'peer']\n ", max_length=64)), - ('urls', models.JSONField(blank=True, default=dict, help_text='URL configurations for node', null=True)), - ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create time of network')), - ('status', models.CharField(choices=[('created', 'Created'), ('restarting', 'Restarting'), ('running', 'Running'), ('removing', 'Removing'), ('paused', 'Paused'), ('exited', 'Exited'), ('dead', 'Dead')], default='created', help_text='Status of node', max_length=64)), - ('config_file', models.TextField(help_text='Config file of node', null=True)), - ('msp', models.TextField(help_text='msp of node', null=True)), - ('tls', models.TextField(help_text='tls of node', null=True)), - ('cid', models.CharField(default='', help_text='id used in agent, such as container id', max_length=256)), - ('agent', models.ForeignKey(help_text='Agent of node', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='node', to='api.agent')), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of node", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="", help_text="Node name", max_length=64 + ), + ), + ( + "type", + models.CharField( + help_text="\n Node type defined for network.\n Fabric available types: ['ca', 'orderer', 'peer']\n ", + max_length=64, + ), + ), + ( + "urls", + models.JSONField( + blank=True, + default=dict, + help_text="URL configurations for node", + null=True, + ), + ), + ( + "created_at", + models.DateTimeField( + auto_now_add=True, help_text="Create time of network" + ), + ), + ( + "status", + models.CharField( + choices=[ + ("created", "Created"), + ("restarting", "Restarting"), + ("running", "Running"), + ("removing", "Removing"), + ("paused", "Paused"), + ("exited", "Exited"), + ("dead", "Dead"), + ], + default="created", + help_text="Status of node", + max_length=64, + ), + ), + ( + "config_file", + models.TextField( + help_text="Config file of node", null=True + ), + ), + ("msp", models.TextField(help_text="msp of node", null=True)), + ("tls", models.TextField(help_text="tls of node", null=True)), + ( + "cid", + models.CharField( + default="", + help_text="id used in agent, such as container id", + max_length=256, + ), + ), + ( + "agent", + models.ForeignKey( + help_text="Agent of node", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="node", + to="api.agent", + ), + ), ], options={ - 'ordering': ('-created_at',), + "ordering": ("-created_at",), }, ), migrations.CreateModel( - name='NodeUser', + name="NodeUser", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(default='', help_text='User name of node', max_length=64)), - ('secret', models.CharField(default='', help_text='User secret of node', max_length=64)), - ('user_type', models.CharField(choices=[('peer', 'Peer'), ('orderer', 'Orderer'), ('user', 'User')], default='peer', help_text='User type of node', max_length=64)), - ('status', models.CharField(choices=[('registering', 'Registering'), ('registered', 'Registered'), ('fail', 'Fail')], default='registering', help_text='Status of node user', max_length=32)), - ('attrs', models.CharField(default='', help_text='Attributes of node user', max_length=512)), - ('node', models.ForeignKey(help_text='Node of user', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.node')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "name", + models.CharField( + default="", + help_text="User name of node", + max_length=64, + ), + ), + ( + "secret", + models.CharField( + default="", + help_text="User secret of node", + max_length=64, + ), + ), + ( + "user_type", + models.CharField( + choices=[ + ("peer", "Peer"), + ("orderer", "Orderer"), + ("user", "User"), + ], + default="peer", + help_text="User type of node", + max_length=64, + ), + ), + ( + "status", + models.CharField( + choices=[ + ("registering", "Registering"), + ("registered", "Registered"), + ("fail", "Fail"), + ], + default="registering", + help_text="Status of node user", + max_length=32, + ), + ), + ( + "attrs", + models.CharField( + default="", + help_text="Attributes of node user", + max_length=512, + ), + ), + ( + "node", + models.ForeignKey( + help_text="Node of user", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.node", + ), + ), ], options={ - 'ordering': ('id',), + "ordering": ("id",), }, ), migrations.CreateModel( - name='Organization', + name="Organization", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of organization', primary_key=True, serialize=False)), - ('name', models.CharField(default='', help_text='Name of organization', max_length=64)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('msp', models.TextField(help_text='msp of organization', null=True)), - ('tls', models.TextField(help_text='tls of organization', null=True)), - ('agents', models.CharField(default='', help_text='agent of organization', max_length=128)), - ('network', models.ForeignKey(help_text='Network to which the organization belongs', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='organization', to='api.network')), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of organization", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="", + help_text="Name of organization", + max_length=64, + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ( + "msp", + models.TextField( + help_text="msp of organization", null=True + ), + ), + ( + "tls", + models.TextField( + help_text="tls of organization", null=True + ), + ), + ( + "agents", + models.CharField( + default="", + help_text="agent of organization", + max_length=128, + ), + ), + ( + "network", + models.ForeignKey( + help_text="Network to which the organization belongs", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="organization", + to="api.network", + ), + ), ], options={ - 'ordering': ('-created_at',), + "ordering": ("-created_at",), }, ), migrations.CreateModel( - name='PeerCa', + name="PeerCa", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('address', models.CharField(default='', help_text='Node Address of ca', max_length=128)), - ('certificate', models.FileField(blank=True, help_text='Certificate file for ca node.', max_length=256, null=True, upload_to=api.models.get_ca_certificate_path)), - ('type', models.CharField(choices=[('tls', 'TLS'), ('signature', 'Signature')], default='signature', help_text='Type of ca node for peer', max_length=64)), - ('node', models.ForeignKey(help_text='CA node of peer', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.node')), - ('peer', models.ForeignKey(help_text='Peer node', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.fabricpeer')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "address", + models.CharField( + default="", + help_text="Node Address of ca", + max_length=128, + ), + ), + ( + "certificate", + models.FileField( + blank=True, + help_text="Certificate file for ca node.", + max_length=256, + null=True, + upload_to=api.models.get_ca_certificate_path, + ), + ), + ( + "type", + models.CharField( + choices=[("tls", "TLS"), ("signature", "Signature")], + default="signature", + help_text="Type of ca node for peer", + max_length=64, + ), + ), + ( + "node", + models.ForeignKey( + help_text="CA node of peer", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.node", + ), + ), + ( + "peer", + models.ForeignKey( + help_text="Peer node", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.fabricpeer", + ), + ), ], ), migrations.CreateModel( - name='User', + name="User", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of user', primary_key=True, serialize=False)), - ('name', models.CharField(help_text='user name', max_length=128)), - ('roles', models.CharField(help_text='roles of user', max_length=128)), - ('attributes', models.CharField(help_text='attributes of user', max_length=128)), - ('revoked', models.CharField(help_text='revoked of user', max_length=128)), - ('create_ts', models.DateTimeField(auto_now_add=True, help_text='Create time of user')), - ('msp', models.TextField(help_text='msp of user', null=True)), - ('tls', models.TextField(help_text='tls of user', null=True)), - ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.organization')), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of user", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField(help_text="user name", max_length=128), + ), + ( + "roles", + models.CharField( + help_text="roles of user", max_length=128 + ), + ), + ( + "attributes", + models.CharField( + help_text="attributes of user", max_length=128 + ), + ), + ( + "revoked", + models.CharField( + help_text="revoked of user", max_length=128 + ), + ), + ( + "create_ts", + models.DateTimeField( + auto_now_add=True, help_text="Create time of user" + ), + ), + ("msp", models.TextField(help_text="msp of user", null=True)), + ("tls", models.TextField(help_text="tls of user", null=True)), + ( + "organization", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="api.organization", + ), + ), ], ), migrations.CreateModel( - name='Port', + name="Port", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('external', models.IntegerField(default=0, help_text='External port', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)])), - ('internal', models.IntegerField(default=0, help_text='Internal port', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)])), - ('node', models.ForeignKey(help_text='Node of port', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='port', to='api.node')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "external", + models.IntegerField( + default=0, + help_text="External port", + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(65535), + ], + ), + ), + ( + "internal", + models.IntegerField( + default=0, + help_text="Internal port", + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(65535), + ], + ), + ), + ( + "node", + models.ForeignKey( + help_text="Node of port", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="port", + to="api.node", + ), + ), ], options={ - 'ordering': ('external',), + "ordering": ("external",), }, ), migrations.CreateModel( - name='PeerCaUser', + name="PeerCaUser", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('username', models.CharField(default='', help_text='If user not set, set username/password', max_length=64)), - ('password', models.CharField(default='', help_text='If user not set, set username/password', max_length=64)), - ('type', models.CharField(choices=[('peer', 'Peer'), ('orderer', 'Orderer'), ('user', 'User')], default='user', help_text='User type of ca', max_length=64)), - ('peer_ca', models.ForeignKey(help_text='Peer Ca configuration', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.peerca')), - ('user', models.ForeignKey(help_text='User of ca node', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.nodeuser')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "username", + models.CharField( + default="", + help_text="If user not set, set username/password", + max_length=64, + ), + ), + ( + "password", + models.CharField( + default="", + help_text="If user not set, set username/password", + max_length=64, + ), + ), + ( + "type", + models.CharField( + choices=[ + ("peer", "Peer"), + ("orderer", "Orderer"), + ("user", "User"), + ], + default="user", + help_text="User type of ca", + max_length=64, + ), + ), + ( + "peer_ca", + models.ForeignKey( + help_text="Peer Ca configuration", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.peerca", + ), + ), + ( + "user", + models.ForeignKey( + help_text="User of ca node", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.nodeuser", + ), + ), ], ), migrations.AddField( - model_name='node', - name='organization', - field=models.ForeignKey(help_text='Organization of node', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='node', to='api.organization'), + model_name="node", + name="organization", + field=models.ForeignKey( + help_text="Organization of node", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="node", + to="api.organization", + ), ), migrations.AddField( - model_name='node', - name='user', - field=models.ForeignKey(help_text='User of node', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + model_name="node", + name="user", + field=models.ForeignKey( + help_text="User of node", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), ), migrations.CreateModel( - name='KubernetesConfig', + name="KubernetesConfig", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('credential_type', models.CharField(choices=[('cert_key', 'CertKey'), ('config', 'Config'), ('username_password', 'UsernamePassword')], default='cert_key', help_text='Credential type of k8s', max_length=32)), - ('enable_ssl', models.BooleanField(default=False, help_text='Whether enable ssl for api')), - ('ssl_ca', models.TextField(blank=True, default='', help_text='Ca file content for ssl')), - ('nfs_server', models.CharField(blank=True, default='', help_text='NFS server address for k8s', max_length=256)), - ('parameters', models.JSONField(blank=True, default=dict, help_text='Extra parameters for kubernetes', null=True)), - ('cert', models.TextField(blank=True, default='', help_text='Cert content for k8s')), - ('key', models.TextField(blank=True, default='', help_text='Key content for k8s')), - ('username', models.CharField(blank=True, default='', help_text='Username for k8s credential', max_length=128)), - ('password', models.CharField(blank=True, default='', help_text='Password for k8s credential', max_length=128)), - ('agent', models.ForeignKey(help_text='Agent of kubernetes config', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.agent')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "credential_type", + models.CharField( + choices=[ + ("cert_key", "CertKey"), + ("config", "Config"), + ("username_password", "UsernamePassword"), + ], + default="cert_key", + help_text="Credential type of k8s", + max_length=32, + ), + ), + ( + "enable_ssl", + models.BooleanField( + default=False, help_text="Whether enable ssl for api" + ), + ), + ( + "ssl_ca", + models.TextField( + blank=True, + default="", + help_text="Ca file content for ssl", + ), + ), + ( + "nfs_server", + models.CharField( + blank=True, + default="", + help_text="NFS server address for k8s", + max_length=256, + ), + ), + ( + "parameters", + models.JSONField( + blank=True, + default=dict, + help_text="Extra parameters for kubernetes", + null=True, + ), + ), + ( + "cert", + models.TextField( + blank=True, + default="", + help_text="Cert content for k8s", + ), + ), + ( + "key", + models.TextField( + blank=True, default="", help_text="Key content for k8s" + ), + ), + ( + "username", + models.CharField( + blank=True, + default="", + help_text="Username for k8s credential", + max_length=128, + ), + ), + ( + "password", + models.CharField( + blank=True, + default="", + help_text="Password for k8s credential", + max_length=128, + ), + ), + ( + "agent", + models.ForeignKey( + help_text="Agent of kubernetes config", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.agent", + ), + ), ], ), migrations.CreateModel( - name='File', + name="File", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, help_text='ID of file', primary_key=True, serialize=False)), - ('name', models.CharField(default='', help_text='File name', max_length=64)), - ('file', models.FileField(blank=True, help_text='File', max_length=256, upload_to=api.models.get_file_path)), - ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create time of agent')), - ('type', models.CharField(choices=[('certificate', 'Certificate')], default='certificate', help_text='File type', max_length=32)), - ('organization', models.ForeignKey(help_text='Organization of file', null=True, on_delete=django.db.models.deletion.CASCADE, to='api.organization')), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + help_text="ID of file", + primary_key=True, + serialize=False, + ), + ), + ( + "name", + models.CharField( + default="", help_text="File name", max_length=64 + ), + ), + ( + "file", + models.FileField( + blank=True, + help_text="File", + max_length=256, + upload_to=api.models.get_file_path, + ), + ), + ( + "created_at", + models.DateTimeField( + auto_now_add=True, help_text="Create time of agent" + ), + ), + ( + "type", + models.CharField( + choices=[("certificate", "Certificate")], + default="certificate", + help_text="File type", + max_length=32, + ), + ), + ( + "organization", + models.ForeignKey( + help_text="Organization of file", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="api.organization", + ), + ), ], options={ - 'ordering': ('-created_at',), + "ordering": ("-created_at",), }, ), migrations.CreateModel( - name='Channel', + name="Channel", fields=[ - ('id', models.UUIDField(default=api.utils.common.make_uuid, editable=False, help_text='ID of Channel', primary_key=True, serialize=False, unique=True)), - ('name', models.CharField(help_text='name of channel', max_length=128)), - ('create_ts', models.DateTimeField(auto_now_add=True, help_text='Create time of Channel')), - ('config', models.JSONField(blank=True, default=dict, help_text='Channel config', null=True)), - ('network', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.network')), - ('orderers', models.ManyToManyField(help_text='Orderer list in the channel', to='api.node')), - ('organizations', models.ManyToManyField(help_text='the organization of the channel', related_name='channels', to='api.organization')), + ( + "id", + models.UUIDField( + default=api.utils.common.make_uuid, + editable=False, + help_text="ID of Channel", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "name", + models.CharField( + help_text="name of channel", max_length=128 + ), + ), + ( + "create_ts", + models.DateTimeField( + auto_now_add=True, help_text="Create time of Channel" + ), + ), + ( + "config", + models.JSONField( + blank=True, + default=dict, + help_text="Channel config", + null=True, + ), + ), + ( + "network", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="api.network", + ), + ), + ( + "orderers", + models.ManyToManyField( + help_text="Orderer list in the channel", to="api.node" + ), + ), + ( + "organizations", + models.ManyToManyField( + help_text="the organization of the channel", + related_name="channels", + to="api.organization", + ), + ), ], ), migrations.AddField( - model_name='agent', - name='organization', - field=models.ForeignKey(help_text='Organization of agent', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='agent', to='api.organization'), + model_name="agent", + name="organization", + field=models.ForeignKey( + help_text="Organization of agent", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="agent", + to="api.organization", + ), ), migrations.AddField( - model_name='userprofile', - name='organization', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='users', to='api.organization'), + model_name="userprofile", + name="organization", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="users", + to="api.organization", + ), ), migrations.AddField( - model_name='userprofile', - name='user_permissions', - field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions'), + model_name="userprofile", + name="user_permissions", + field=models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), ), ] diff --git a/src/api-engine/api/migrations/0002_userprofile_created_at_alter_agent_name_and_more.py b/src/api-engine/api/migrations/0002_userprofile_created_at_alter_agent_name_and_more.py index e7c3ebec7..99c4d5cc7 100644 --- a/src/api-engine/api/migrations/0002_userprofile_created_at_alter_agent_name_and_more.py +++ b/src/api-engine/api/migrations/0002_userprofile_created_at_alter_agent_name_and_more.py @@ -7,29 +7,43 @@ class Migration(migrations.Migration): dependencies = [ - ('api', '0001_initial'), + ("api", "0001_initial"), ] operations = [ migrations.AddField( - model_name='userprofile', - name='created_at', - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + model_name="userprofile", + name="created_at", + field=models.DateTimeField( + auto_now_add=True, default=django.utils.timezone.now + ), preserve_default=False, ), migrations.AlterField( - model_name='agent', - name='name', - field=models.CharField(blank=True, help_text='Agent name, can be generated automatically.', max_length=64, unique=True), + model_name="agent", + name="name", + field=models.CharField( + blank=True, + help_text="Agent name, can be generated automatically.", + max_length=64, + unique=True, + ), ), migrations.AlterField( - model_name='network', - name='name', - field=models.CharField(blank=True, help_text='network name, can be generated automatically.', max_length=64, unique=True), + model_name="network", + name="name", + field=models.CharField( + blank=True, + help_text="network name, can be generated automatically.", + max_length=64, + unique=True, + ), ), migrations.AlterField( - model_name='node', - name='name', - field=models.CharField(blank=True, help_text='Node name', max_length=64, unique=True), + model_name="node", + name="name", + field=models.CharField( + blank=True, help_text="Node name", max_length=64, unique=True + ), ), ] diff --git a/src/api-engine/api/models.py b/src/api-engine/api/models.py index f456d9d6b..1c83d0477 100644 --- a/src/api-engine/api/models.py +++ b/src/api-engine/api/models.py @@ -83,7 +83,7 @@ class Organization(models.Model): help_text="Network to which the organization belongs", null=True, related_name="organization", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) # channel = models.ForeignKey( # "Channel", @@ -106,9 +106,7 @@ class UserProfile(AbstractUser): ) email = models.EmailField(db_index=True, unique=True) username = models.CharField( - default="", - max_length=64, - help_text="Name of user" + default="", max_length=64, help_text="Name of user" ) role = models.CharField( choices=UserRole.to_choices(True), @@ -116,10 +114,13 @@ class UserProfile(AbstractUser): max_length=64, ) organization = models.ForeignKey( - Organization, null=True, on_delete=models.CASCADE, related_name="users", + Organization, + null=True, + on_delete=models.CASCADE, + related_name="users", ) created_at = models.DateTimeField(auto_now_add=True) - USERNAME_FIELD = 'email' + USERNAME_FIELD = "email" REQUIRED_FIELDS = [] class Meta: @@ -171,10 +172,7 @@ class Agent(models.Model): blank=True ) urls = models.CharField( - help_text="Agent URL", - null=True, - blank=True, - validators=[validate_url] + help_text="Agent URL", null=True, blank=True, validators=[validate_url] ) organization = models.ForeignKey( "Organization", @@ -212,7 +210,7 @@ class Agent(models.Model): free_ports = ArrayField( models.IntegerField(blank=True), help_text="Agent free ports.", - null=True + null=True, ) def save(self, *args, **kwargs): @@ -311,7 +309,7 @@ class Network(models.Model): help_text="network name, can be generated automatically.", max_length=64, unique=True, - blank=True + blank=True, ) type = models.CharField( help_text="Type of network, %s" % NetworkType.values(), @@ -331,14 +329,18 @@ class Network(models.Model): help_text="Create time of network", auto_now_add=True ) consensus = models.CharField( - help_text="Consensus of network", max_length=128, default="raft", + help_text="Consensus of network", + max_length=128, + default="raft", ) genesisblock = models.TextField( help_text="genesis block", null=True, ) database = models.CharField( - help_text="database of network", max_length=128, default="leveldb", + help_text="database of network", + max_length=128, + default="leveldb", ) class Meta: @@ -489,7 +491,9 @@ class Node(models.Model): default=make_uuid, editable=True, ) - name = models.CharField(help_text="Node name", max_length=64, unique=True, blank=True) + name = models.CharField( + help_text="Node name", max_length=64, unique=True, blank=True + ) type = models.CharField( help_text=""" Node type defined for network. @@ -522,7 +526,7 @@ class Node(models.Model): help_text="Agent of node", null=True, related_name="node", - on_delete=models.CASCADE + on_delete=models.CASCADE, ) # network = models.ForeignKey( # Network, @@ -630,7 +634,11 @@ class Meta: class Port(models.Model): node = models.ForeignKey( - Node, help_text="Node of port", on_delete=models.CASCADE, null=True, related_name="port", + Node, + help_text="Node of port", + on_delete=models.CASCADE, + null=True, + related_name="port", ) external = models.IntegerField( help_text="External port", @@ -711,20 +719,15 @@ class User(models.Model): default=make_uuid, editable=True, ) - name = models.CharField( - help_text="user name", max_length=128 - ) - roles = models.CharField( - help_text="roles of user", max_length=128 - ) + name = models.CharField(help_text="user name", max_length=128) + roles = models.CharField(help_text="roles of user", max_length=128) organization = models.ForeignKey( - "Organization", on_delete=models.CASCADE) + "Organization", on_delete=models.CASCADE + ) attributes = models.CharField( help_text="attributes of user", max_length=128 ) - revoked = models.CharField( - help_text="revoked of user", max_length=128 - ) + revoked = models.CharField(help_text="revoked of user", max_length=128) create_ts = models.DateTimeField( help_text="Create time of user", auto_now_add=True ) @@ -744,10 +747,9 @@ class Channel(models.Model): help_text="ID of Channel", default=make_uuid, editable=False, - unique=True) - name = models.CharField( - help_text="name of channel", max_length=128 + unique=True, ) + name = models.CharField(help_text="name of channel", max_length=128) organizations = models.ManyToManyField( to="Organization", help_text="the organization of the channel", @@ -757,9 +759,7 @@ class Channel(models.Model): create_ts = models.DateTimeField( help_text="Create time of Channel", auto_now_add=True ) - network = models.ForeignKey( - "Network", on_delete=models.CASCADE - ) + network = models.ForeignKey("Network", on_delete=models.CASCADE) orderers = models.ManyToManyField( to="Node", help_text="Orderer list in the channel", @@ -816,16 +816,15 @@ class ChainCode(models.Model): help_text="ID of ChainCode", default=make_uuid, editable=False, - unique=True + unique=True, ) package_id = models.CharField( - help_text="package_id of chainCode", max_length=128, + help_text="package_id of chainCode", + max_length=128, editable=False, - unique=True - ) - label = models.CharField( - help_text="label of chainCode", max_length=128 + unique=True, ) + label = models.CharField(help_text="label of chainCode", max_length=128) creator = models.CharField( help_text="creator of chainCode", max_length=128 ) @@ -833,7 +832,10 @@ class ChainCode(models.Model): help_text="language of chainCode", max_length=128 ) description = models.CharField( - help_text="description of chainCode", max_length=128, blank=True, null=True + help_text="description of chainCode", + max_length=128, + blank=True, + null=True, ) create_ts = models.DateTimeField( help_text="Create time of chainCode", auto_now_add=True diff --git a/src/api-engine/api/routes/agent/serializers.py b/src/api-engine/api/routes/agent/serializers.py index 85cb6f951..3c5039604 100644 --- a/src/api-engine/api/routes/agent/serializers.py +++ b/src/api-engine/api/routes/agent/serializers.py @@ -254,7 +254,7 @@ class Meta: fields = ( "type", # "capacity" - ) + ) extra_kwargs = { "type": {"required": True}, # "capacity": {"required": True}, diff --git a/src/api-engine/api/routes/agent/views.py b/src/api-engine/api/routes/agent/views.py index 3a6a04392..6f5d06cbf 100644 --- a/src/api-engine/api/routes/agent/views.py +++ b/src/api-engine/api/routes/agent/views.py @@ -38,7 +38,10 @@ class AgentViewSet(viewsets.ViewSet): """Class represents agent related operations.""" - permission_classes = [IsAuthenticated, ] + + permission_classes = [ + IsAuthenticated, + ] @swagger_auto_schema( query_serializer=AgentQuery, @@ -101,7 +104,11 @@ def list(self, request): "status": agent.status, "type": agent.type, "urls": agent.urls, - "organization": str(agent.organization.id) if agent.organization else None, + "organization": ( + str(agent.organization.id) + if agent.organization + else None + ), "created_at": agent.created_at, } for agent in agents @@ -115,9 +122,7 @@ def list(self, request): ok(response.validated_data), status=status.HTTP_200_OK ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( request_body=AgentCreateBody, @@ -148,9 +153,7 @@ def create(self, request): } if name: - agent_count = Agent.objects.filter( - name=name - ).count() + agent_count = Agent.objects.filter(name=name).count() if agent_count > 0: raise ResourceExists("Agent Exists") @@ -171,14 +174,13 @@ def create(self, request): response = AgentIDSerializer(data=agent.__dict__) if response.is_valid(raise_exception=True): return Response( - ok(response.validated_data), status=status.HTTP_201_CREATED + ok(response.validated_data), + status=status.HTTP_201_CREATED, ) except ResourceExists as e: raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( responses=with_common_response( @@ -243,9 +245,7 @@ def update(self, request, pk=None): except ResourceExists as e: raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( request_body=AgentPatchBody, @@ -280,9 +280,7 @@ def partial_update(self, request, pk=None): except ResourceNotFound as e: raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( responses=with_common_response( @@ -318,9 +316,7 @@ def destroy(self, request, pk=None): except (ResourceNotFound, ResourceInUse) as e: raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( method="post", @@ -372,9 +368,7 @@ def apply(self, request): raise e except Exception as e: LOG.exception("Agent Not Applied") - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( method="delete", @@ -409,6 +403,4 @@ def release(self, request, pk=None): except ResourceNotFound as e: raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) diff --git a/src/api-engine/api/routes/chaincode/serializers.py b/src/api-engine/api/routes/chaincode/serializers.py index 63f67c5b4..a2ff77004 100644 --- a/src/api-engine/api/routes/chaincode/serializers.py +++ b/src/api-engine/api/routes/chaincode/serializers.py @@ -10,7 +10,7 @@ def upload_to(instance, filename): - return '/'.join([FABRIC_CHAINCODE_STORE, instance.user_name, filename]) + return "/".join([FABRIC_CHAINCODE_STORE, instance.user_name, filename]) class ChainCodeIDSerializer(serializers.Serializer): @@ -30,7 +30,7 @@ def validate(self, attrs): @staticmethod def extension_for_file(file): - extension = file.name.endswith('.tar.gz') + extension = file.name.endswith(".tar.gz") return extension @@ -42,17 +42,28 @@ class ChainCodeNetworkSerializer(serializers.Serializer): class ChainCodeOrgListSerializer(serializers.Serializer): id = serializers.UUIDField(help_text="Organization ID") name = serializers.CharField( - max_length=128, help_text="name of Organization") + max_length=128, help_text="name of Organization" + ) -class ChainCodeResponseSerializer(ChainCodeIDSerializer, serializers.ModelSerializer): +class ChainCodeResponseSerializer( + ChainCodeIDSerializer, serializers.ModelSerializer +): id = serializers.UUIDField(help_text="ID of ChainCode") # network = ChainCodeNetworkSerializer() # organizations = ChainCodeOrgListSerializer(many=True) class Meta: model = ChainCode - fields = ("id", "package_id", "label", "creator", "language", "create_ts", "description") + fields = ( + "id", + "package_id", + "label", + "creator", + "language", + "create_ts", + "description", + ) class ChaincodeListResponse(ListResponseSerializer): @@ -64,7 +75,9 @@ class ChainCodeApproveForMyOrgBody(serializers.Serializer): chaincode_name = serializers.CharField(max_length=128, required=True) chaincode_version = serializers.CharField(max_length=128, required=True) sequence = serializers.IntegerField(min_value=1, required=True) - policy = serializers.CharField(max_length=128, required=False, allow_blank=True) + policy = serializers.CharField( + max_length=128, required=False, allow_blank=True + ) init_flag = serializers.BooleanField(required=False) diff --git a/src/api-engine/api/routes/chaincode/views.py b/src/api-engine/api/routes/chaincode/views.py index d03038918..aafeef4d1 100644 --- a/src/api-engine/api/routes/chaincode/views.py +++ b/src/api-engine/api/routes/chaincode/views.py @@ -14,11 +14,7 @@ from drf_yasg.utils import swagger_auto_schema from api.config import FABRIC_CHAINCODE_STORE from api.config import CELLO_HOME -from api.models import ( - Node, - ChainCode, - Channel -) +from api.models import Node, ChainCode, Channel from api.utils.common import make_uuid from django.core.paginator import Paginator @@ -32,7 +28,7 @@ ChainCodeIDSerializer, ChainCodeCommitBody, ChainCodeApproveForMyOrgBody, - ChaincodeListResponse + ChaincodeListResponse, ) from api.common import ok, err import threading @@ -45,7 +41,10 @@ class ChainCodeViewSet(viewsets.ViewSet): """Class represents Channel related operations.""" - permission_classes = [IsAuthenticated, ] + + permission_classes = [ + IsAuthenticated, + ] def _read_cc_pkg(self, pk, filename, ccpackage_path): """ @@ -57,7 +56,9 @@ def _read_cc_pkg(self, pk, filename, ccpackage_path): try: meta_path = os.path.join(ccpackage_path, "metadata.json") # extract metadata file - with tarfile.open(os.path.join(ccpackage_path, filename)) as tared_file: + with tarfile.open( + os.path.join(ccpackage_path, filename) + ) as tared_file: metadata_file = None for member in tared_file.getmembers(): if member.name.endswith("metadata.json"): @@ -66,8 +67,11 @@ def _read_cc_pkg(self, pk, filename, ccpackage_path): if metadata_file is not None: # Extract the metadata file - metadata_content = tared_file.extractfile( - metadata_file).read().decode("utf-8") + metadata_content = ( + tared_file.extractfile(metadata_file) + .read() + .decode("utf-8") + ) metadata = json.loads(metadata_content) language = metadata["type"] label = metadata["label"] @@ -106,7 +110,8 @@ def list(self, request): try: org = request.user.organization chaincodes = ChainCode.objects.filter( - creator=org.name).order_by("create_ts") + creator=org.name + ).order_by("create_ts") p = Paginator(chaincodes, per_page) chaincodes_pages = p.page(page) chanincodes_list = [ @@ -122,11 +127,11 @@ def list(self, request): for chaincode in chaincodes_pages ] response = ChaincodeListResponse( - {"data": chanincodes_list, "total": chaincodes.count()}) + {"data": chanincodes_list, "total": chaincodes.count()} + ) return Response( - data=ok( - response.data), - status=status.HTTP_200_OK) + data=ok(response.data), status=status.HTTP_200_OK + ) except Exception as e: return Response( err(e.args), status=status.HTTP_400_BAD_REQUEST @@ -139,7 +144,7 @@ def list(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['post'], url_path="chaincodeRepo") + @action(detail=False, methods=["post"], url_path="chaincodeRepo") def package(self, request): serializer = ChainCodePackageBody(data=request.data) if serializer.is_valid(raise_exception=True): @@ -149,7 +154,7 @@ def package(self, request): try: fd, temp_cc_path = tempfile.mkstemp() # try to calculate packageid - with open(fd, 'wb') as f: + with open(fd, "wb") as f: for chunk in file.chunks(): f.write(chunk) @@ -163,14 +168,20 @@ def package(self, request): if metadata_file is not None: # Extract the metadata file - metadata_content = tar.extractfile( - metadata_file).read().decode("utf-8") + metadata_content = ( + tar.extractfile(metadata_file) + .read() + .decode("utf-8") + ) metadata = json.loads(metadata_content) label = metadata.get("label") else: return Response( - err("Metadata file not found in the chaincode package."), - status=status.HTTP_400_BAD_REQUEST) + err( + "Metadata file not found in the chaincode package." + ), + status=status.HTTP_400_BAD_REQUEST, + ) org = request.user.organization # qs = Node.objects.filter(type="peer", organization=org) @@ -201,8 +212,12 @@ def package(self, request): cc = ChainCode.objects.filter(package_id=packageid) if cc.exists(): return Response( - err("package with id {} already exists.".format(packageid)), - status=status.HTTP_400_BAD_REQUEST + err( + "package with id {} already exists.".format( + packageid + ) + ), + status=status.HTTP_400_BAD_REQUEST, ) chaincode = ChainCode( @@ -214,7 +229,9 @@ def package(self, request): chaincode.save() # save chaincode package locally - ccpackage_path = os.path.join(FABRIC_CHAINCODE_STORE, packageid) + ccpackage_path = os.path.join( + FABRIC_CHAINCODE_STORE, packageid + ) if not os.path.exists(ccpackage_path): os.makedirs(ccpackage_path) ccpackage = os.path.join(ccpackage_path, file.name) @@ -224,14 +241,13 @@ def package(self, request): try: threading.Thread( target=self._read_cc_pkg, - args=(uuid, file.name, ccpackage_path)).start() + args=(uuid, file.name, ccpackage_path), + ).start() except Exception as e: LOG.exception("Failed Threading") raise e - return Response( - ok("success"), status=status.HTTP_200_OK - ) + return Response(ok("success"), status=status.HTTP_200_OK) except Exception as e: return Response( err(e.args), status=status.HTTP_400_BAD_REQUEST @@ -245,7 +261,7 @@ def package(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['post']) + @action(detail=False, methods=["post"]) def install(self, request): chaincode_id = request.data.get("id") # Get the selected node ID from request @@ -263,11 +279,12 @@ def install(self, request): if node_id: try: peer_node = Node.objects.get( - id=node_id, type="peer", organization=org) + id=node_id, type="peer", organization=org + ) except Node.DoesNotExist: return Response( err("Selected peer node not found or not authorized."), - status=status.HTTP_404_NOT_FOUND + status=status.HTTP_404_NOT_FOUND, ) else: # Fallback to first peer if no node selected @@ -282,14 +299,11 @@ def install(self, request): if res != 0: return Response( err("install chaincode failed."), - status=status.HTTP_400_BAD_REQUEST) + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) - return Response( - ok("success"), status=status.HTTP_200_OK - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) + return Response(ok("success"), status=status.HTTP_200_OK) @swagger_auto_schema( method="get", @@ -297,7 +311,7 @@ def install(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def query_installed(self, request): try: org = request.user.organization @@ -309,17 +323,17 @@ def query_installed(self, request): timeout = "5s" peer_channel_cli = PeerChainCode(**envs) - res, installed_chaincodes = peer_channel_cli.lifecycle_query_installed( - timeout) + res, installed_chaincodes = ( + peer_channel_cli.lifecycle_query_installed(timeout) + ) if res != 0: - return Response(err("query installed chaincode failed."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("query installed chaincode failed."), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) - return Response( - ok(installed_chaincodes), status=status.HTTP_200_OK - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) + return Response(ok(installed_chaincodes), status=status.HTTP_200_OK) @swagger_auto_schema( method="get", @@ -327,7 +341,7 @@ def query_installed(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def get_installed_package(self, request): try: org = request.user.organization @@ -341,15 +355,14 @@ def get_installed_package(self, request): peer_channel_cli = PeerChainCode(**envs) res = peer_channel_cli.lifecycle_get_installed_package(timeout) if res != 0: - return Response(err("get installed package failed."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("get installed package failed."), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) - return Response( - ok("success"), status=status.HTTP_200_OK - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) + return Response(ok("success"), status=status.HTTP_200_OK) @swagger_auto_schema( method="post", @@ -357,14 +370,18 @@ def get_installed_package(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['post']) + @action(detail=False, methods=["post"]) def approve_for_my_org(self, request): serializer = ChainCodeApproveForMyOrgBody(data=request.data) if serializer.is_valid(raise_exception=True): try: channel_name = serializer.validated_data.get("channel_name") - chaincode_name = serializer.validated_data.get("chaincode_name") - chaincode_version = serializer.validated_data.get("chaincode_version") + chaincode_name = serializer.validated_data.get( + "chaincode_name" + ) + chaincode_version = serializer.validated_data.get( + "chaincode_version" + ) policy = serializer.validated_data.get("policy", "") sequence = serializer.validated_data.get("sequence") init_flag = serializer.validated_data.get("init_flag", False) @@ -374,7 +391,13 @@ def approve_for_my_org(self, request): if not qs.exists(): raise ResourceNotFound("Orderer Does Not Exist") orderer_node = qs.first() - orderer_url = orderer_node.name + "." + org.name.split(".", 1)[1] + ":" + str(7050) + orderer_url = ( + orderer_node.name + + "." + + org.name.split(".", 1)[1] + + ":" + + str(7050) + ) qs = Node.objects.filter(type="peer", organization=org) if not qs.exists(): @@ -383,17 +406,28 @@ def approve_for_my_org(self, request): envs = init_env_vars(peer_node, org) peer_channel_cli = PeerChainCode(**envs) - code, content = peer_channel_cli.lifecycle_approve_for_my_org(orderer_url, channel_name, - chaincode_name, chaincode_version, sequence, policy, init_flag) + code, content = peer_channel_cli.lifecycle_approve_for_my_org( + orderer_url, + channel_name, + chaincode_name, + chaincode_version, + sequence, + policy, + init_flag, + ) if code != 0: - return Response(err(" lifecycle_approve_for_my_org failed. err: " + content), status=status.HTTP_400_BAD_REQUEST) + return Response( + err( + " lifecycle_approve_for_my_org failed. err: " + + content + ), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: return Response( err(e.args), status=status.HTTP_400_BAD_REQUEST ) - return Response( - ok("success"), status=status.HTTP_200_OK - ) + return Response(ok("success"), status=status.HTTP_200_OK) @swagger_auto_schema( method="get", @@ -401,7 +435,7 @@ def approve_for_my_org(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def query_approved(self, request): try: org = request.user.organization @@ -416,17 +450,17 @@ def query_approved(self, request): peer_channel_cli = PeerChainCode(**envs) code, content = peer_channel_cli.lifecycle_query_approved( - channel_name, cc_name) + channel_name, cc_name + ) if code != 0: - return Response(err("query_approved failed."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("query_approved failed."), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) - return Response( - ok(content), status=status.HTTP_200_OK - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) + return Response(ok(content), status=status.HTTP_200_OK) @swagger_auto_schema( method="post", @@ -434,15 +468,18 @@ def query_approved(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['post']) + @action(detail=False, methods=["post"]) def check_commit_readiness(self, request): serializer = ChainCodeApproveForMyOrgBody(data=request.data) if serializer.is_valid(raise_exception=True): try: channel_name = serializer.validated_data.get("channel_name") - chaincode_name = serializer.validated_data.get("chaincode_name") + chaincode_name = serializer.validated_data.get( + "chaincode_name" + ) chaincode_version = serializer.validated_data.get( - "chaincode_version") + "chaincode_version" + ) policy = serializer.validated_data.get("policy") # Perhaps the orderer's port is best stored in the database orderer_url = serializer.validated_data.get("orderer_url") @@ -453,9 +490,12 @@ def check_commit_readiness(self, request): raise ResourceNotFound("Orderer Does Not Exist") orderer_node = qs.first() - orderer_tls_dir = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/msp/tlscacerts" \ - .format(CELLO_HOME, org.name, org.name.split(".", 1)[1], orderer_node.name + "." + - org.name.split(".", 1)[1]) + orderer_tls_dir = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/msp/tlscacerts".format( + CELLO_HOME, + org.name, + org.name.split(".", 1)[1], + orderer_node.name + "." + org.name.split(".", 1)[1], + ) orderer_tls_root_cert = "" for _, _, files in os.walk(orderer_tls_dir): @@ -469,25 +509,36 @@ def check_commit_readiness(self, request): envs = init_env_vars(peer_node, org) peer_channel_cli = PeerChainCode(**envs) - code, content = peer_channel_cli.lifecycle_check_commit_readiness(orderer_url, orderer_tls_root_cert, - channel_name, chaincode_name, - chaincode_version, policy, sequence) + code, content = ( + peer_channel_cli.lifecycle_check_commit_readiness( + orderer_url, + orderer_tls_root_cert, + channel_name, + chaincode_name, + chaincode_version, + policy, + sequence, + ) + ) if code != 0: - return Response(err("check_commit_readiness failed."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("check_commit_readiness failed."), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: return Response( err(e.args), status=status.HTTP_400_BAD_REQUEST ) - return Response( - ok(content), status=status.HTTP_200_OK - ) + return Response(ok(content), status=status.HTTP_200_OK) def _get_orderer_url(self, org): qs = Node.objects.filter(type="orderer", organization=org) if not qs.exists(): raise ResourceNotFound("Orderer Does Not Exist") - return qs.first().name + "." + org.name.split(".", 1)[1] + ":" + str(7050) + return ( + qs.first().name + "." + org.name.split(".", 1)[1] + ":" + str(7050) + ) def _get_peer_channel_cli(self, org): qs = Node.objects.filter(type="peer", organization=org) @@ -496,15 +547,29 @@ def _get_peer_channel_cli(self, org): envs = init_env_vars(qs.first(), org) return PeerChainCode(**envs) - def _get_approved_organizations_by_channel_and_chaincode(self, peer_channel_cli, channel_name, chaincode_name, chaincode_version, sequence): - code, readiness_result = peer_channel_cli.lifecycle_check_commit_readiness( - channel_name, chaincode_name, chaincode_version, sequence) + def _get_approved_organizations_by_channel_and_chaincode( + self, + peer_channel_cli, + channel_name, + chaincode_name, + chaincode_version, + sequence, + ): + code, readiness_result = ( + peer_channel_cli.lifecycle_check_commit_readiness( + channel_name, chaincode_name, chaincode_version, sequence + ) + ) if code != 0: - raise Exception(f"Check commit readiness failed: {readiness_result}") + raise Exception( + f"Check commit readiness failed: {readiness_result}" + ) # Check approved status approvals = readiness_result.get("approvals", {}) - approved_msps = [org_msp for org_msp, approved in approvals.items() if approved] + approved_msps = [ + org_msp for org_msp, approved in approvals.items() if approved + ] if not approved_msps: raise Exception("No organizations have approved this chaincode") @@ -521,12 +586,16 @@ def _get_approved_organizations_by_channel_and_chaincode(self, peer_channel_cli, approved_orgs = [] for msp_id in approved_msps: if msp_id.endswith("MSP"): - org_prefix = msp_id[:-3].lower() # remove "MSP" and convert to lowercase + org_prefix = msp_id[ + :-3 + ].lower() # remove "MSP" and convert to lowercase # find the corresponding organization in the channel for channel_org in channel_orgs: if channel_org.name.split(".")[0] == org_prefix: approved_orgs.append(channel_org) - LOG.info(f"Found approved organization: {channel_org.name} (MSP: {msp_id})") + LOG.info( + f"Found approved organization: {channel_org.name} (MSP: {msp_id})" + ) break if not approved_orgs: @@ -539,16 +608,15 @@ def _get_peer_addresses_and_certs_by_organizations(self, orgs): for org in orgs: qs = Node.objects.filter(type="peer", organization=org) if not qs.exists(): - LOG.warning(f"No peer nodes found for organization: {org.name}") + LOG.warning( + f"No peer nodes found for organization: {org.name}" + ) continue # select the first peer node for each organization peer = qs.first() peer_tls_cert = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/tls/ca.crt".format( - CELLO_HOME, - org.name, - org.name, - peer.name + "." + org.name + CELLO_HOME, org.name, org.name, peer.name + "." + org.name ) peer_address = peer.name + "." + org.name + ":" + str(7051) LOG.info(f"Added peer from org {org.name}: {peer_address}") @@ -566,14 +634,18 @@ def _get_peer_addresses_and_certs_by_organizations(self, orgs): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['post']) + @action(detail=False, methods=["post"]) def commit(self, request): serializer = ChainCodeCommitBody(data=request.data) if serializer.is_valid(raise_exception=True): try: channel_name = serializer.validated_data.get("channel_name") - chaincode_name = serializer.validated_data.get("chaincode_name") - chaincode_version = serializer.validated_data.get("chaincode_version") + chaincode_name = serializer.validated_data.get( + "chaincode_name" + ) + chaincode_version = serializer.validated_data.get( + "chaincode_version" + ) policy = serializer.validated_data.get("policy") sequence = serializer.validated_data.get("sequence") init_flag = serializer.validated_data.get("init_flag", False) @@ -583,43 +655,65 @@ def commit(self, request): # Step 1: Check commit readiness, find all approved organizations peer_channel_cli = self._get_peer_channel_cli(org) - approved_organizations = self._get_approved_organizations_by_channel_and_chaincode( - peer_channel_cli, - channel_name, - chaincode_name, - chaincode_version, - sequence + approved_organizations = ( + self._get_approved_organizations_by_channel_and_chaincode( + peer_channel_cli, + channel_name, + chaincode_name, + chaincode_version, + sequence, + ) ) # Step 2: Get peer nodes and root certs - peer_address_list, peer_root_certs = self._get_peer_addresses_and_certs_by_organizations(approved_organizations) + peer_address_list, peer_root_certs = ( + self._get_peer_addresses_and_certs_by_organizations( + approved_organizations + ) + ) # Step 3: Commit chaincode code = peer_channel_cli.lifecycle_commit( - orderer_url, channel_name, chaincode_name, chaincode_version, - sequence, policy, peer_address_list, peer_root_certs, init_flag) + orderer_url, + channel_name, + chaincode_name, + chaincode_version, + sequence, + policy, + peer_address_list, + peer_root_certs, + init_flag, + ) if code != 0: return Response( err("Commit chaincode failed"), - status=status.HTTP_400_BAD_REQUEST + status=status.HTTP_400_BAD_REQUEST, ) LOG.info(f"Chaincode {chaincode_name} committed successfully") # Step 4: Query committed chaincode - code, committed_result = peer_channel_cli.lifecycle_query_committed( - channel_name, chaincode_name) + code, committed_result = ( + peer_channel_cli.lifecycle_query_committed( + channel_name, chaincode_name + ) + ) if code == 0: LOG.info(committed_result) - return Response(ok(committed_result), status=status.HTTP_200_OK) + return Response( + ok(committed_result), status=status.HTTP_200_OK + ) else: - return Response(err("Query committed failed."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("Query committed failed."), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: LOG.error(f"Commit chaincode failed: {str(e)}") return Response( err(f"Commit chaincode failed: {str(e)}"), - status=status.HTTP_400_BAD_REQUEST + status=status.HTTP_400_BAD_REQUEST, ) @swagger_auto_schema( @@ -628,7 +722,7 @@ def commit(self, request): {status.HTTP_201_CREATED: ChainCodeIDSerializer} ), ) - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def query_committed(self, request): try: channel_name = request.data.get("channel_name") @@ -640,15 +734,17 @@ def query_committed(self, request): peer_node = qs.first() envs = init_env_vars(peer_node, org) peer_channel_cli = PeerChainCode(**envs) - code, chaincodes_commited = peer_channel_cli.lifecycle_query_committed( - channel_name, chaincode_name) + code, chaincodes_commited = ( + peer_channel_cli.lifecycle_query_committed( + channel_name, chaincode_name + ) + ) if code != 0: - return Response(err("query committed failed."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("query committed failed."), + status=status.HTTP_400_BAD_REQUEST, + ) except Exception as e: LOG.exception("Could Not Commit Query") - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) - return Response( - ok(chaincodes_commited), status=status.HTTP_200_OK - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) + return Response(ok(chaincodes_commited), status=status.HTTP_200_OK) diff --git a/src/api-engine/api/routes/channel/serializers.py b/src/api-engine/api/routes/channel/serializers.py index 165c12b65..e4a0d2b82 100644 --- a/src/api-engine/api/routes/channel/serializers.py +++ b/src/api-engine/api/routes/channel/serializers.py @@ -37,16 +37,19 @@ class ChannelIDSerializer(serializers.Serializer): class ChannelUpdateSerializer(serializers.Serializer): msp_id = serializers.CharField( - max_length=128, help_text="MSP ID of Organization") + max_length=128, help_text="MSP ID of Organization" + ) data = serializers.FileField(help_text="Channel config file") org_type = serializers.ChoiceField( - help_text="Organization type", choices=ORG_CHOICES) + help_text="Organization type", choices=ORG_CHOICES + ) class ChannelOrgListSerializer(serializers.Serializer): id = serializers.UUIDField(help_text="Organization ID") name = serializers.CharField( - max_length=128, help_text="name of Organization") + max_length=128, help_text="name of Organization" + ) class ChannelNetworkSerializer(serializers.Serializer): @@ -54,7 +57,9 @@ class ChannelNetworkSerializer(serializers.Serializer): name = serializers.CharField(max_length=128, help_text="name of Network") -class ChannelResponseSerializer(ChannelIDSerializer, serializers.ModelSerializer): +class ChannelResponseSerializer( + ChannelIDSerializer, serializers.ModelSerializer +): id = serializers.UUIDField(help_text="ID of Channel") network = ChannelNetworkSerializer() organizations = ChannelOrgListSerializer(many=True) diff --git a/src/api-engine/api/routes/channel/views.py b/src/api-engine/api/routes/channel/views.py index 20af8470b..e004a2496 100644 --- a/src/api-engine/api/routes/channel/views.py +++ b/src/api-engine/api/routes/channel/views.py @@ -18,14 +18,19 @@ from api.config import CELLO_HOME from api.common.serializers import PageQuerySerializer -from api.utils.common import with_common_response, parse_block_file, to_dict, json_filter, json_add_anchor_peer, json_create_envelope, init_env_vars +from api.utils.common import ( + with_common_response, + parse_block_file, + to_dict, + json_filter, + json_add_anchor_peer, + json_create_envelope, + init_env_vars, +) from api.lib.configtxgen import ConfigTX, ConfigTxGen from api.lib.peer.channel import Channel as PeerChannel from api.lib.configtxlator.configtxlator import ConfigTxLator -from api.exceptions import ( - ResourceNotFound, - NoResource -) +from api.exceptions import ResourceNotFound, NoResource from api.models import ( Channel, Node, @@ -36,7 +41,7 @@ ChannelIDSerializer, ChannelListResponse, ChannelResponseSerializer, - ChannelUpdateSerializer + ChannelUpdateSerializer, ) from api.common import ok, err @@ -59,7 +64,10 @@ class ChannelViewSet(viewsets.ViewSet): """Class represents Channel related operations.""" - permission_classes = [IsAuthenticated, ] + + permission_classes = [ + IsAuthenticated, + ] parser_classes = [MultiPartParser, FormParser, JSONParser] @swagger_auto_schema( @@ -82,8 +90,9 @@ def list(self, request): try: org = request.user.organization - channels = Channel.objects.filter( - organizations=org).order_by("create_ts") + channels = Channel.objects.filter(organizations=org).order_by( + "create_ts" + ) p = Paginator(channels, per_page) channels_pages = p.page(page) channels_list = [ @@ -91,14 +100,20 @@ def list(self, request): "id": channel.id, "name": channel.name, "network": channel.network.__dict__, - "organizations": [{"id": org.id, "name": org.name} for org in channel.organizations.all()], + "organizations": [ + {"id": org.id, "name": org.name} + for org in channel.organizations.all() + ], "create_ts": channel.create_ts, } for channel in channels_pages ] response = ChannelListResponse( - {"data": channels_list, "total": channels.count()}) - return Response(data=ok(response.data), status=status.HTTP_200_OK) + {"data": channels_list, "total": channels.count()} + ) + return Response( + data=ok(response.data), status=status.HTTP_200_OK + ) except Exception as e: return Response( err(e.args), status=status.HTTP_400_BAD_REQUEST @@ -136,8 +151,14 @@ def create(self, request): # assemble transaction config _orderers, _peers = assemble_transaction_config(org) - ConfigTX(org.network.name).create(name, org.network.consensus, _orderers, _peers) - ConfigTxGen(org.network.name).genesis(profile=name, channelid=name, outputblock="{}.block".format(name)) + ConfigTX(org.network.name).create( + name, org.network.consensus, _orderers, _peers + ) + ConfigTxGen(org.network.name).genesis( + profile=name, + channelid=name, + outputblock="{}.block".format(name), + ) # osnadmin channel join ordering_node = Node.objects.get(id=orderers[0]) @@ -151,10 +172,7 @@ def create(self, request): set_anchor_peer(name, org, anchor_peer, ordering_node) # save channel to db - channel = Channel( - name=name, - network=org.network - ) + channel = Channel(name=name, network=org.network) channel.save() channel.organizations.add(org) channel.orderers.add(ordering_node) @@ -163,7 +181,8 @@ def create(self, request): response = ChannelIDSerializer(data=channel.__dict__) if response.is_valid(raise_exception=True): return Response( - ok(response.validated_data), status=status.HTTP_201_CREATED + ok(response.validated_data), + status=status.HTTP_201_CREATED, ) except Exception as e: return Response( @@ -172,7 +191,8 @@ def create(self, request): @swagger_auto_schema( responses=with_common_response( - {status.HTTP_200_OK: ChannelResponseSerializer}), + {status.HTTP_200_OK: ChannelResponseSerializer} + ), ) def retrieve(self, request, pk=None): """ @@ -209,21 +229,27 @@ def update(self, request, pk=None): org = request.user.organization try: # Read uploaded file in cache without saving it on disk. - file = request.FILES.get('data').read() - json_data = file.decode('utf8').replace("'", '"') + file = request.FILES.get("data").read() + json_data = file.decode("utf8").replace("'", '"') data = json.loads(json_data) msp_id = serializer.validated_data.get("msp_id") org_type = serializer.validated_data.get("org_type") # Validate uploaded config file try: - config = data["config"]["channel_group"]["groups"][org_type]["groups"][msp_id] + config = data["config"]["channel_group"]["groups"][ + org_type + ]["groups"][msp_id] except KeyError: LOG.exception("config file not found") raise ResourceNotFound try: # Read current channel config from local disk - with open(channel.get_channel_artifacts_path(CFG_JSON), 'r', encoding='utf-8') as f: + with open( + channel.get_channel_artifacts_path(CFG_JSON), + "r", + encoding="utf-8", + ) as f: LOG.info("load current config success") current_config = json.load(f) except FileNotFoundError: @@ -236,11 +262,17 @@ def update(self, request, pk=None): ) LOG.info("new org created") updated_config = deepcopy(current_config) - updated_config["channel_group"]["groups"]["Application"]["groups"][msp_id] = config + updated_config["channel_group"]["groups"]["Application"][ + "groups" + ][msp_id] = config LOG.info("update config success", updated_config) # Update and save the config with new org - with open(channel.get_channel_artifacts_path(UPDATED_CFG_JSON), 'w', encoding='utf-8') as f: + with open( + channel.get_channel_artifacts_path(UPDATED_CFG_JSON), + "w", + encoding="utf-8", + ) as f: LOG.info("save updated config success") json.dump(updated_config, f, sort_keys=False) @@ -275,12 +307,14 @@ def update(self, request, pk=None): "type": 2, } }, - "data": { - "config_update": to_dict(config_update) - } + "data": {"config_update": to_dict(config_update)}, } } - with open(channel.get_channel_artifacts_path(CFG_JSON), 'w', encoding='utf-8') as f: + with open( + channel.get_channel_artifacts_path(CFG_JSON), + "w", + encoding="utf-8", + ) as f: LOG.info("save config to json success") json.dump(updated_config, f, sort_keys=False) @@ -288,7 +322,9 @@ def update(self, request, pk=None): ConfigTxLator().proto_encode( input=channel.get_channel_artifacts_path(CFG_JSON), type="common.Envelope", - output=channel.get_channel_artifacts_path(CFG_DELTA_ENV_PB), + output=channel.get_channel_artifacts_path( + CFG_DELTA_ENV_PB + ), ) LOG.info("Encode the config update envelope success") @@ -296,18 +332,22 @@ def update(self, request, pk=None): nodes = Node.objects.filter( organization=org, type=FabricNodeType.Peer.name.lower(), - status=NodeStatus.Running.name.lower() + status=NodeStatus.Running.name.lower(), ) for node in nodes: dir_node = "{}/{}/crypto-config/peerOrganizations".format( - CELLO_HOME, org.name) + CELLO_HOME, org.name + ) env = { - "FABRIC_CFG_PATH": "{}/{}/peers/{}/".format(dir_node, org.name, node.name + "." + org.name), + "FABRIC_CFG_PATH": "{}/{}/peers/{}/".format( + dir_node, org.name, node.name + "." + org.name + ), } cli = PeerChannel(**env) cli.signconfigtx( - channel.get_channel_artifacts_path(CFG_DELTA_ENV_PB)) + channel.get_channel_artifacts_path(CFG_DELTA_ENV_PB) + ) LOG.info("Peers to send the update transaction success") # Save a new organization to db. @@ -330,18 +370,23 @@ def get_channel_org_config(self, request, pk=None): node = Node.objects.filter( organization=org, type=FabricNodeType.Peer.name.lower(), - status=NodeStatus.Running.name.lower() + status=NodeStatus.Running.name.lower(), ).first() dir_node = "{}/{}/crypto-config/peerOrganizations".format( - CELLO_HOME, org.name) + CELLO_HOME, org.name + ) env = { - "FABRIC_CFG_PATH": "{}/{}/peers/{}/".format(dir_node, org.name, node.name + "." + org.name), + "FABRIC_CFG_PATH": "{}/{}/peers/{}/".format( + dir_node, org.name, node.name + "." + org.name + ), } peer_channel_cli = PeerChannel(**env) peer_channel_cli.fetch(option="config", channel=channel.name) # Decode latest config block into json - config = ConfigTxLator().proto_decode(input=path, type="common.Block") + config = ConfigTxLator().proto_decode( + input=path, type="common.Block" + ) config = parse_block_file(config) # Prepare return data @@ -349,11 +394,15 @@ def get_channel_org_config(self, request, pk=None): "config": config, "organization": org.name, # TODO: create a method on Organization or Node to return msp_id - "msp_id": '{}'.format(org.name.split(".")[0].capitalize()) + "msp_id": "{}".format(org.name.split(".")[0].capitalize()), } # Save as a json file for future usage - with open(channel.get_channel_artifacts_path(CFG_JSON), 'w', encoding='utf-8') as f: + with open( + channel.get_channel_artifacts_path(CFG_JSON), + "w", + encoding="utf-8", + ) as f: json.dump(config, f, sort_keys=False) # Encode block file as pb ConfigTxLator().proto_encode( @@ -409,14 +458,9 @@ def osn_channel_join(name, ordering_node, org): peer_channel_cli.create( channel=name, orderer_admin_url="{}.{}:{}".format( - ordering_node.name, - org.name.split(".", 1)[1], str(7053) + ordering_node.name, org.name.split(".", 1)[1], str(7053) ), - block_path="{}/{}/{}.block".format( - CELLO_HOME, - org.network.name, - name - ) + block_path="{}/{}/{}.block".format(CELLO_HOME, org.network.name, name), ) @@ -434,7 +478,8 @@ def peer_channel_join(name, peers, org): peer_channel_cli = PeerChannel(**envs) peer_channel_cli.join( block_path="{}/{}/{}.block".format( - CELLO_HOME, org.network.name, name) + CELLO_HOME, org.network.name, name + ) ) @@ -446,7 +491,7 @@ def set_anchor_peer(name, org, anchor_peer, ordering_node): :param ordering_node: Orderer node :return: none """ - org_msp = '{}'.format(org.name.split(".", 1)[0].capitalize()) + org_msp = "{}".format(org.name.split(".", 1)[0].capitalize()) channel_artifacts_path = "{}/{}".format(CELLO_HOME, org.network.name) # Fetch the channel block from the orderer @@ -463,7 +508,7 @@ def set_anchor_peer(name, org, anchor_peer, ordering_node): json_filter( input="{}/config_block.json".format(channel_artifacts_path), output="{}/config.json".format(channel_artifacts_path), - expression=".data.data[0].payload.data.config" + expression=".data.data[0].payload.data.config", ) # add anchor peer config @@ -472,13 +517,10 @@ def set_anchor_peer(name, org, anchor_peer, ordering_node): "mod_policy": "Admins", "value": { "anchor_peers": [ - { - "host": anchor_peer.name + "." + org.name, - "port": 7051 - } + {"host": anchor_peer.name + "." + org.name, "port": 7051} ] }, - "version": 0 + "version": 0, } } @@ -486,7 +528,7 @@ def set_anchor_peer(name, org, anchor_peer, ordering_node): input="{}/config.json".format(channel_artifacts_path), output="{}/modified_config.json".format(channel_artifacts_path), anchor_peer_config=anchor_peer_config, - org_msp=org_msp + org_msp=org_msp, ) ConfigTxLator().proto_encode( @@ -517,18 +559,26 @@ def set_anchor_peer(name, org, anchor_peer, ordering_node): # Create config update envelope json_create_envelope( input="{}/config_update.json".format(channel_artifacts_path), - output="{}/config_update_in_envelope.json".format(channel_artifacts_path), - channel=name + output="{}/config_update_in_envelope.json".format( + channel_artifacts_path + ), + channel=name, ) ConfigTxLator().proto_encode( - input="{}/config_update_in_envelope.json".format(channel_artifacts_path), + input="{}/config_update_in_envelope.json".format( + channel_artifacts_path + ), type="common.Envelope", - output="{}/config_update_in_envelope.pb".format(channel_artifacts_path), + output="{}/config_update_in_envelope.pb".format( + channel_artifacts_path + ), ) # Update the channel of anchor peer - peer_channel_update(name, org, anchor_peer, ordering_node, channel_artifacts_path) + peer_channel_update( + name, org, anchor_peer, ordering_node, channel_artifacts_path + ) def peer_channel_fetch(name, org, anchor_peer, ordering_node): @@ -542,16 +592,19 @@ def peer_channel_fetch(name, org, anchor_peer, ordering_node): envs = init_env_vars(anchor_peer, org) peer_channel_cli = PeerChannel(**envs) peer_channel_cli.fetch( - block_path="{}/{}/config_block.pb".format(CELLO_HOME, org.network.name), - channel=name, orderer_general_url="{}.{}:{}".format( - ordering_node.name, - org.name.split(".", 1)[1], - str(7050) - ) + block_path="{}/{}/config_block.pb".format( + CELLO_HOME, org.network.name + ), + channel=name, + orderer_general_url="{}.{}:{}".format( + ordering_node.name, org.name.split(".", 1)[1], str(7050) + ), ) -def peer_channel_update(name, org, anchor_peer, ordering_node, channel_artifacts_path): +def peer_channel_update( + name, org, anchor_peer, ordering_node, channel_artifacts_path +): """ Update the channel. :param anchor_peer: Anchor peer node @@ -563,7 +616,10 @@ def peer_channel_update(name, org, anchor_peer, ordering_node, channel_artifacts peer_channel_cli = PeerChannel(**envs) peer_channel_cli.update( channel=name, - channel_tx="{}/config_update_in_envelope.pb".format(channel_artifacts_path), + channel_tx="{}/config_update_in_envelope.pb".format( + channel_artifacts_path + ), orderer_url="{}.{}:{}".format( - ordering_node.name, org.name.split(".", 1)[1], str(7050)), + ordering_node.name, org.name.split(".", 1)[1], str(7050) + ), ) diff --git a/src/api-engine/api/routes/general/serializers.py b/src/api-engine/api/routes/general/serializers.py index 9f41fc9ff..af9fcd6ce 100644 --- a/src/api-engine/api/routes/general/serializers.py +++ b/src/api-engine/api/routes/general/serializers.py @@ -9,9 +9,11 @@ class RegisterBody(serializers.Serializer): orgName = serializers.CharField(help_text="name of Organization") email = serializers.EmailField(help_text="email of user") username = serializers.CharField( - help_text="name of Administrator", default="Administator") + help_text="name of Administrator", default="Administator" + ) password = serializers.CharField( - help_text="password of Administrator", default="666666") + help_text="password of Administrator", default="666666" + ) class RegisterIDSerializer(serializers.Serializer): diff --git a/src/api-engine/api/routes/general/views.py b/src/api-engine/api/routes/general/views.py index f9bfcfb91..8470e3fed 100644 --- a/src/api-engine/api/routes/general/views.py +++ b/src/api-engine/api/routes/general/views.py @@ -15,7 +15,6 @@ from api.routes.general.serializers import ( RegisterBody, RegisterResponse, - ) from api.models import UserProfile, Organization from rest_framework.response import Response @@ -33,9 +32,8 @@ RefreshToken, AccessToken, ) -from rest_framework_simplejwt.exceptions import ( - TokenError -) +from rest_framework_simplejwt.exceptions import TokenError + LOG = logging.getLogger(__name__) @@ -54,11 +52,13 @@ def create(self, request): pass except MultipleObjectsReturned: return Response( - err("Email Aleady exists!"), status=status.HTTP_409_CONFLICT + err("Email Aleady exists!"), + status=status.HTTP_409_CONFLICT, ) else: return Response( - err("Email Aleady exists!"), status=status.HTTP_409_CONFLICT + err("Email Aleady exists!"), + status=status.HTTP_409_CONFLICT, ) try: @@ -67,11 +67,13 @@ def create(self, request): pass except MultipleObjectsReturned: return Response( - err("Orgnization already exists!"), status=status.HTTP_409_CONFLICT + err("Orgnization already exists!"), + status=status.HTTP_409_CONFLICT, ) else: return Response( - err("Orgnization already exists!"), status=status.HTTP_409_CONFLICT + err("Orgnization already exists!"), + status=status.HTTP_409_CONFLICT, ) CryptoConfig(orgname).create(0, 0) @@ -89,17 +91,14 @@ def create(self, request): user.set_password(password) user.save() - response = RegisterResponse( - data={"id": organization.id} - ) + response = RegisterResponse(data={"id": organization.id}) if response.is_valid(raise_exception=True): return Response( - data=ok(response.validated_data), status=status.HTTP_200_OK + data=ok(response.validated_data), + status=status.HTTP_200_OK, ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) def _conversion_msp_tls(self, name): """ @@ -110,8 +109,9 @@ def _conversion_msp_tls(self, name): :rtype: bytes """ try: - dir_org = "{}/{}/crypto-config/peerOrganizations/{}/" \ - .format(CELLO_HOME, name, name) + dir_org = "{}/{}/crypto-config/peerOrganizations/{}/".format( + CELLO_HOME, name, name + ) zip_dir("{}msp".format(dir_org), "{}msp.zip".format(dir_org)) with open("{}msp.zip".format(dir_org), "rb") as f_msp: @@ -133,14 +133,14 @@ def post(self, request, *args, **kwargs): if serializer.is_valid(raise_exception=True): user = authenticate( request, - username=serializer.validated_data['email'], - password=serializer.validated_data['password'], + username=serializer.validated_data["email"], + password=serializer.validated_data["password"], ) if user is not None: refresh = RefreshToken.for_user(user) data = { - 'token': str(refresh.access_token), - 'user': user, + "token": str(refresh.access_token), + "user": user, } response = LoginSuccessBody(instance=data) return Response( @@ -158,11 +158,11 @@ def post(self, request, *args, **kwargs): access_token = AccessToken( token=serializer.validated_data["token"], ) - user = UserProfile.objects.get(pk=access_token['user_id']) + user = UserProfile.objects.get(pk=access_token["user_id"]) if user is not None: data = { - 'token': str(access_token.token), - 'user': user, + "token": str(access_token.token), + "user": user, } response = LoginSuccessBody(instance=data) return Response( @@ -171,9 +171,6 @@ def post(self, request, *args, **kwargs): ) except TokenError: LOG.exception("invalid token error") - return Response( - data=err(msg="invalid token"), - status=401 - ) + return Response(data=err(msg="invalid token"), status=401) return super().post(request, *args, **kwargs) diff --git a/src/api-engine/api/routes/network/serializers.py b/src/api-engine/api/routes/network/serializers.py index cb698699e..0d95a4594 100644 --- a/src/api-engine/api/routes/network/serializers.py +++ b/src/api-engine/api/routes/network/serializers.py @@ -70,9 +70,11 @@ class NetworkCreateBody(serializers.ModelSerializer): class Meta: model = Network fields = ("name", "consensus", "database") - extra_kwargs = {"name": {"required": True}, - "consensus": {"required": True}, - "database": {"required": True}} + extra_kwargs = { + "name": {"required": True}, + "consensus": {"required": True}, + "database": {"required": True}, + } class NetworkMemberResponse(serializers.Serializer): diff --git a/src/api-engine/api/routes/network/views.py b/src/api-engine/api/routes/network/views.py index 116381c54..a86b447a0 100644 --- a/src/api-engine/api/routes/network/views.py +++ b/src/api-engine/api/routes/network/views.py @@ -34,7 +34,9 @@ class NetworkViewSet(viewsets.ViewSet): - permission_classes = [IsAuthenticated, ] + permission_classes = [ + IsAuthenticated, + ] def _genesis2base64(self, network): """ @@ -47,8 +49,9 @@ def _genesis2base64(self, network): dir_node = "{}/{}/".format(CELLO_HOME, network) name = "genesis.block" zname = "block.zip" - zip_file("{}{}".format(dir_node, name), - "{}{}".format(dir_node, zname)) + zip_file( + "{}{}".format(dir_node, name), "{}{}".format(dir_node, zname) + ) with open("{}{}".format(dir_node, zname), "rb") as f_block: block = base64.b64encode(f_block.read()) return block @@ -77,7 +80,10 @@ def list(self, request): org = request.user.organization networks = org.network if not networks: - return Response(ok(data={"total": 0, "data": None}), status=status.HTTP_200_OK) + return Response( + ok(data={"total": 0, "data": None}), + status=status.HTTP_200_OK, + ) p = Paginator([networks], per_page) networks = p.page(page) networks = [ @@ -95,11 +101,11 @@ def list(self, request): return Response( ok(response.validated_data), status=status.HTTP_200_OK ) - return Response(ok(data={"total": 0, "data": None}), status=status.HTTP_200_OK) - except Exception as e: return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST + ok(data={"total": 0, "data": None}), status=status.HTTP_200_OK ) + except Exception as e: + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) def _agent_params(self, pk): """ @@ -124,8 +130,9 @@ def _agent_params(self, pk): info = {} - org_name = org.name if node.type == "peer" else org.name.split(".", 1)[ - 1] + org_name = ( + org.name if node.type == "peer" else org.name.split(".", 1)[1] + ) # get info of node, e.g, tls, msp, config. info["status"] = node.status info["msp"] = node.msp @@ -189,18 +196,21 @@ def create(self, request): org = request.user.organization if org.network: raise ResourceExists( - detail="Network exists for the organization") + detail="Network exists for the organization" + ) network = Network( - name=name, consensus=consensus, database=database) + name=name, consensus=consensus, database=database + ) network.save() org.network = network org.save() nodes = Node.objects.filter(organization=org) for node in nodes: try: - threading.Thread(target=self._start_node, - args=(node.id,)).start() + threading.Thread( + target=self._start_node, args=(node.id,) + ).start() except Exception as e: LOG.exception("Network Not Created") raise e @@ -208,15 +218,14 @@ def create(self, request): response = NetworkIDSerializer(data=network.__dict__) if response.is_valid(raise_exception=True): return Response( - ok(response.validated_data), status=status.HTTP_201_CREATED + ok(response.validated_data), + status=status.HTTP_201_CREATED, ) except ResourceExists as e: LOG.exception("Network Exists") raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema(responses=with_common_response()) def retrieve(self, request, pk=None): @@ -248,9 +257,7 @@ def destroy(self, request, pk=None): return Response(ok(None), status=status.HTTP_202_ACCEPTED) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( methods=["get"], diff --git a/src/api-engine/api/routes/node/serializers.py b/src/api-engine/api/routes/node/serializers.py index c0855deb4..067699dab 100644 --- a/src/api-engine/api/routes/node/serializers.py +++ b/src/api-engine/api/routes/node/serializers.py @@ -248,9 +248,7 @@ class Meta: class NodeStatusSerializer(NodeIDSerializer, serializers.ModelSerializer): class Meta: model = Node - fields = ( - "status", - ) + fields = ("status",) extra_kwargs = { "id": {"required": True, "read_only": False}, "created_at": {"required": True, "read_only": False}, @@ -331,6 +329,7 @@ class Meta: model = Node fields = ("files",) + # class NodeFileCreateSerializer(serializers.ModelSerializer): # def to_form_paras(self): # custom_paras = to_form_paras(self) diff --git a/src/api-engine/api/routes/node/views.py b/src/api-engine/api/routes/node/views.py index d9950ba6a..e51e17ae9 100644 --- a/src/api-engine/api/routes/node/views.py +++ b/src/api-engine/api/routes/node/views.py @@ -19,7 +19,12 @@ from rest_framework.permissions import IsAuthenticated from api.common.enums import AgentOperation -from api.exceptions import CustomError, NoResource, ResourceExists, ResourceInUse +from api.exceptions import ( + CustomError, + NoResource, + ResourceExists, + ResourceInUse, +) from api.exceptions import ResourceNotFound from api.models import ( Node, @@ -52,11 +57,7 @@ from api.utils.common import with_common_response from api.lib.pki import CryptoGen, CryptoConfig from api.utils import zip_dir, zip_file -from api.config import ( - CELLO_HOME, - FABRIC_NODE, - PRODUCTION_NODE -) +from api.config import CELLO_HOME, FABRIC_NODE, PRODUCTION_NODE from api.utils.node_config import NodeConfig from api.lib.agent import AgentHandler from api.lib.peer.channel import Channel as PeerChannel @@ -68,7 +69,9 @@ class NodeViewSet(viewsets.ViewSet): - permission_classes = [IsAuthenticated, ] + permission_classes = [ + IsAuthenticated, + ] parser_classes = [MultiPartParser, FormParser, JSONParser] # Only operator can update node info @@ -128,12 +131,13 @@ def list(self, request, *args, **kwargs): p = Paginator(nodes, per_page) nodes = p.page(page) response = NodeListSerializer( - {"total": p.count, "data": nodes}) - return Response(data=ok(response.data), status=status.HTTP_200_OK) + {"total": p.count, "data": nodes} + ) + return Response( + data=ok(response.data), status=status.HTTP_200_OK + ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) def _save_fabric_ca(self, request, ca=None): if ca is None: @@ -283,21 +287,22 @@ def create(self, request): agent = organization.agent.get() if agent: nodes = Node.objects.filter( - name=node_name, organization=organization, type=node_type) + name=node_name, + organization=organization, + type=node_type, + ) if nodes: raise ResourceExists("Node Exists") else: raise NoResource("Node Does Not Exist") urls = "{}.{}".format(node_name, organization.name) - nodes = { - "type": node_type, - "Specs": [node_name] - } + nodes = {"type": node_type, "Specs": [node_name]} CryptoConfig(organization.name).update(nodes) CryptoGen(organization.name).extend() self._generate_config(node_type, organization.name, node_name) msp, tls, cfg = self._conversion_msp_tls_cfg( - node_type, organization.name, node_name) + node_type, organization.name, node_name + ) node = Node( name=node_name, organization=organization, @@ -306,7 +311,7 @@ def create(self, request): msp=msp, tls=tls, agent=agent, - config_file=cfg + config_file=cfg, ) node.save() @@ -314,7 +319,8 @@ def create(self, request): if node.organization.network: try: threading.Thread( - target=self._start_node, args=(node.id,)).start() + target=self._start_node, args=(node.id,) + ).start() except Exception as e: LOG.exception("Thread Failed") raise e @@ -322,14 +328,13 @@ def create(self, request): response = NodeIDSerializer(data=node.__dict__) if response.is_valid(raise_exception=True): return Response( - ok(response.validated_data), status=status.HTTP_201_CREATED + ok(response.validated_data), + status=status.HTTP_201_CREATED, ) except (ResourceExists, NoResource) as e: raise e except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) def _set_port(self, type, node, agent): """ @@ -347,18 +352,23 @@ def _set_port(self, type, node, agent): ports = find_available_ports(ip, node.id, agent.id, 2) set_ports_mapping( node.id, - [{"internal": 7051, "external": ports[0]}, { - "internal": 9444, "external": ports[1]}], - True) + [ + {"internal": 7051, "external": ports[0]}, + {"internal": 9444, "external": ports[1]}, + ], + True, + ) else: # unify the port mapping for orderer ports = find_available_ports(ip, node.id, agent.id, 3) set_ports_mapping( node.id, - [{"internal": 7050, "external": ports[0]}, { - "internal": 7053, "external": ports[1]}, { - "internal": 9443, "external": ports[2]}], - True + [ + {"internal": 7050, "external": ports[0]}, + {"internal": 7053, "external": ports[1]}, + {"internal": 9443, "external": ports[2]}, + ], + True, ) def _conversion_msp_tls_cfg(self, type, org, node): @@ -373,13 +383,18 @@ def _conversion_msp_tls_cfg(self, type, org, node): """ try: if type == "peer": - dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/" \ - .format(CELLO_HOME, org, org, node + "." + org) + dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/".format( + CELLO_HOME, org, org, node + "." + org + ) name = "core.yaml" cname = "peer_config.zip" else: - dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/" \ - .format(CELLO_HOME, org, org.split(".", 1)[1], node + "." + org.split(".", 1)[1]) + dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/".format( + CELLO_HOME, + org, + org.split(".", 1)[1], + node + "." + org.split(".", 1)[1], + ) name = "orderer.yaml" cname = "orderer_config.zip" @@ -391,8 +406,9 @@ def _conversion_msp_tls_cfg(self, type, org, node): with open("{}tls.zip".format(dir_node), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) - zip_file("{}{}".format(dir_node, name), - "{}{}".format(dir_node, cname)) + zip_file( + "{}{}".format(dir_node, name), "{}{}".format(dir_node, cname) + ) with open("{}{}".format(dir_node, cname), "rb") as f_cfg: cfg = base64.b64encode(f_cfg.read()) except Exception as e: @@ -415,40 +431,87 @@ def _generate_config(self, type, org, node): args = {} if type == "peer": args.update({"peer_tls_enabled": True}) - args.update({"operations_listenAddress": node + "." + org + ":9444"}) + args.update( + {"operations_listenAddress": node + "." + org + ":9444"} + ) args.update({"peer_address": node + "." + org + ":7051"}) args.update({"peer_gossip_bootstrap": node + "." + org + ":7051"}) - args.update({"peer_gossip_externalEndpoint": node + "." + org + ":7051"}) + args.update( + {"peer_gossip_externalEndpoint": node + "." + org + ":7051"} + ) args.update({"peer_id": node + "." + org}) args.update({"peer_localMspId": org.capitalize() + "MSP"}) args.update({"peer_mspConfigPath": "/etc/hyperledger/fabric/msp"}) - args.update({"peer_tls_cert_file": "/etc/hyperledger/fabric/tls/server.crt"}) - args.update({"peer_tls_key_file": "/etc/hyperledger/fabric/tls/server.key"}) - args.update({"peer_tls_rootcert_file": "/etc/hyperledger/fabric/tls/ca.crt"}) + args.update( + { + "peer_tls_cert_file": "/etc/hyperledger/fabric/tls/server.crt" + } + ) + args.update( + {"peer_tls_key_file": "/etc/hyperledger/fabric/tls/server.key"} + ) + args.update( + { + "peer_tls_rootcert_file": "/etc/hyperledger/fabric/tls/ca.crt" + } + ) args.update({"vm_docker_hostConfig_NetworkMode": "cello_net"}) - args.update({"vm_endpoint": 'unix:///host/var/run/docker.sock'}) + args.update({"vm_endpoint": "unix:///host/var/run/docker.sock"}) a = NodeConfig(org) a.peer(node, **args) else: args.update({"Admin_TLS_Enabled": True}) args.update({"Admin_ListenAddress": "0.0.0.0:7053"}) - args.update({"Admin_TLS_Certificate": "/etc/hyperledger/fabric/tls/server.crt"}) - args.update({"Admin_TLS_PrivateKey": "/etc/hyperledger/fabric/tls/server.key"}) + args.update( + { + "Admin_TLS_Certificate": "/etc/hyperledger/fabric/tls/server.crt" + } + ) + args.update( + { + "Admin_TLS_PrivateKey": "/etc/hyperledger/fabric/tls/server.key" + } + ) args.update({"ChannelParticipation_Enabled": True}) - args.update({"General_Cluster_ClientCertificate": "/etc/hyperledger/fabric/tls/server.crt"}) - args.update({"General_Cluster_ClientPrivateKey": "/etc/hyperledger/fabric/tls/server.key"}) + args.update( + { + "General_Cluster_ClientCertificate": "/etc/hyperledger/fabric/tls/server.crt" + } + ) + args.update( + { + "General_Cluster_ClientPrivateKey": "/etc/hyperledger/fabric/tls/server.key" + } + ) args.update({"General_ListenAddress": "0.0.0.0"}) args.update({"General_ListenPort": 7050}) args.update({"General_LocalMSPID": "OrdererMSP"}) args.update({"General_LocalMSPDir": "/etc/hyperledger/fabric/msp"}) args.update({"General_TLS_Enabled": True}) - args.update({"General_TLS_Certificate": "/etc/hyperledger/fabric/tls/server.crt"}) - args.update({"General_TLS_PrivateKey": "/etc/hyperledger/fabric/tls/server.key"}) - args.update({"General_TLS_RootCAs": "[/etc/hyperledger/fabric/tls/ca.crt]"}) + args.update( + { + "General_TLS_Certificate": "/etc/hyperledger/fabric/tls/server.crt" + } + ) + args.update( + { + "General_TLS_PrivateKey": "/etc/hyperledger/fabric/tls/server.key" + } + ) + args.update( + {"General_TLS_RootCAs": "[/etc/hyperledger/fabric/tls/ca.crt]"} + ) args.update({"General_BootstrapMethod": "none"}) args.update({"Metrics_Provider": "prometheus"}) - args.update({"Operations_ListenAddress": node + "." + org.split(".", 1)[1] + ":9443"}) + args.update( + { + "Operations_ListenAddress": node + + "." + + org.split(".", 1)[1] + + ":9443" + } + ) a = NodeConfig(org) a.orderer(node, **args) @@ -474,8 +537,9 @@ def _agent_params(self, pk): raise ResourceNotFound("Port Not Found") info = {} - org_name = org.name if node.type == "peer" else org.name.split(".", 1)[ - 1] + org_name = ( + org.name if node.type == "peer" else org.name.split(".", 1)[1] + ) # get info of node, e.g, tls, msp, config. info["status"] = node.status info["msp"] = node.msp @@ -550,12 +614,11 @@ def operate(self, request, pk=None): ) else: return Response( - ok({"error": "invalid operation"}), status=status.HTTP_201_CREATED + ok({"error": "invalid operation"}), + status=status.HTTP_201_CREATED, ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( responses=with_common_response( @@ -629,9 +692,7 @@ def destroy(self, request, pk=None): raise e except Exception as e: LOG.exception("Node Not Deleted") - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( operation_id="update node", @@ -667,9 +728,8 @@ def update(self, request, pk=None): return Response(status=status.HTTP_202_ACCEPTED) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) + # @swagger_auto_schema( # methods=["post"], # request_body=NodeFileCreateSerializer, @@ -730,23 +790,29 @@ def retrieve(self, request, pk=None): # for port in ports # ] response = NodeStatusSerializer(node) - return Response(ok(data=response.data), status=status.HTTP_200_OK) + return Response( + ok(data=response.data), status=status.HTTP_200_OK + ) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( methods=["get"], responses=with_common_response( - {status.HTTP_200_OK: NodeConfigFileSerializer}), + {status.HTTP_200_OK: NodeConfigFileSerializer} + ), ) @swagger_auto_schema( methods=["post"], request_body=NodeConfigFileSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) - @action(methods=["get", "post"], detail=True, url_path="config", url_name="config") + @action( + methods=["get", "post"], + detail=True, + url_path="config", + url_name="config", + ) def node_config(self, request, pk=None): """ Download/upload the node config file @@ -756,34 +822,37 @@ def node_config(self, request, pk=None): organization = request.user.organization org = organization.name try: - node = Node.objects.get( - id=pk, organization=organization - ) + node = Node.objects.get(id=pk, organization=organization) except ObjectDoesNotExist: raise ResourceNotFound("Node Not Found") # Get file locations based on node type if node.type == "peer": - dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/" \ - .format(CELLO_HOME, org, org, node.name + "." + org) + dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/".format( + CELLO_HOME, org, org, node.name + "." + org + ) cname = "peer_config.zip" name = "core.yaml" else: - dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/" \ - .format(CELLO_HOME, org, org.split(".", 1)[1], node.name + "." + org.split(".", 1)[1]) + dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/".format( + CELLO_HOME, + org, + org.split(".", 1)[1], + node.name + "." + org.split(".", 1)[1], + ) cname = "orderer_config.zip" name = "orderer.yaml" except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) if request.method == "GET": # Get the config file from local storage try: config_file = open("{}{}".format(dir_node, cname), "rb") response = HttpResponse( - config_file, content_type="application/zip") - response['Content-Disposition'] = "attachment; filename={}".format( - cname) + config_file, content_type="application/zip" + ) + response["Content-Disposition"] = ( + "attachment; filename={}".format(cname) + ) return response except Exception as e: LOG.exception("Config File Not Found") @@ -791,20 +860,25 @@ def node_config(self, request, pk=None): elif request.method == "POST": # Update yaml, zip files, and the database field try: - new_config_file = request.data['file'] + new_config_file = request.data["file"] try: yaml.safe_load(new_config_file) except yaml.YAMLError: - return Response(err("Unable to parse this YAML file."), status=status.HTTP_400_BAD_REQUEST) + return Response( + err("Unable to parse this YAML file."), + status=status.HTTP_400_BAD_REQUEST, + ) if os.path.exists("{}{}".format(dir_node, name)): os.remove("{}{}".format(dir_node, name)) - with open("{}{}".format(dir_node, name), 'wb+') as f: + with open("{}{}".format(dir_node, name), "wb+") as f: for chunk in new_config_file.chunks(): f.write(chunk) if os.path.exists("{}{}".format(dir_node, cname)): os.remove("{}{}".format(dir_node, cname)) - zip_file("{}{}".format(dir_node, name), - "{}{}".format(dir_node, cname)) + zip_file( + "{}{}".format(dir_node, name), + "{}{}".format(dir_node, cname), + ) with open("{}{}".format(dir_node, cname), "rb") as f_cfg: cfg = base64.b64encode(f_cfg.read()) node.config_file = cfg @@ -819,35 +893,31 @@ def node_config(self, request, pk=None): @action(methods=["post"], detail=True, url_path="block", url_name="block") def block_file(self, request, pk=None): - ''' + """ Peer join channel by uploading a genesis block file - ''' + """ try: self._validate_organization(request) organization = request.user.organization org = organization.name try: - node = Node.objects.get( - id=pk, organization=organization - ) + node = Node.objects.get(id=pk, organization=organization) except ObjectDoesNotExist: raise ResourceNotFound("Node Not Found") envs = init_env_vars(node, organization) - block_path = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/{}.block" \ - .format(CELLO_HOME, org, org, node.name + "." + org, "channel") - uploaded_block_file = request.data['file'] - with open(block_path, 'wb+') as f: + block_path = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/{}.block".format( + CELLO_HOME, org, org, node.name + "." + org, "channel" + ) + uploaded_block_file = request.data["file"] + with open(block_path, "wb+") as f: for chunk in uploaded_block_file.chunks(): f.write(chunk) peer_channel_cli = PeerChannel(**envs) - peer_channel_cli.join( - block_path) + peer_channel_cli.join(block_path) os.remove(block_path) return Response(status=status.HTTP_202_ACCEPTED) except Exception as e: - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) def _register_user(self, request, pk=None): serializer = NodeUserCreateSerializer(data=request.data) @@ -988,6 +1058,4 @@ def patch_user(self, request, pk=None, user_pk=None): return Response(status=status.HTTP_202_ACCEPTED) except Exception as e: LOG.exception("Patch Failed") - return Response( - err(e.args), status=status.HTTP_400_BAD_REQUEST - ) + return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) diff --git a/src/api-engine/api/routes/organization/serializers.py b/src/api-engine/api/routes/organization/serializers.py index ba388ad9e..9e9838915 100644 --- a/src/api-engine/api/routes/organization/serializers.py +++ b/src/api-engine/api/routes/organization/serializers.py @@ -17,10 +17,12 @@ class Meta: class OrganizationCreateBody(serializers.ModelSerializer): peernum = serializers.IntegerField( - source='org_peernum', help_text="Total number of peer", required=True + source="org_peernum", help_text="Total number of peer", required=True ) orderernum = serializers.IntegerField( - source='org_orderernum', help_text="Total number of orderer", required=True + source="org_orderernum", + help_text="Total number of orderer", + required=True, ) class Meta: diff --git a/src/api-engine/api/routes/organization/views.py b/src/api-engine/api/routes/organization/views.py index 2a8e7e3f5..c7093079b 100644 --- a/src/api-engine/api/routes/organization/views.py +++ b/src/api-engine/api/routes/organization/views.py @@ -75,8 +75,14 @@ def list(self, request): { "id": str(organization.id), "name": organization.name, - "network": str(organization.network.id) if organization.network else None, - "agents": organization.agents if organization.agents else None, + "network": ( + str(organization.network.id) + if organization.network + else None + ), + "agents": ( + organization.agents if organization.agents else None + ), "created_at": organization.created_at, } for organization in organizations @@ -145,11 +151,13 @@ def _create_node(self, org, num, nodeType): :return: null """ for i in range(num): - nodeName = "peer" + \ - str(i) if nodeType == "peer" else "orderer" + str(i) + nodeName = ( + "peer" + str(i) if nodeType == "peer" else "orderer" + str(i) + ) self._generate_config(nodeType, org.name, nodeName) msp, tls, cfg = self._conversion_msp_tls_cfg( - nodeType, org.name, nodeName) + nodeType, org.name, nodeName + ) urls = "{}.{}".format(nodeName, org.name) node = Node( name=nodeName, @@ -159,7 +167,7 @@ def _create_node(self, org, num, nodeType): msp=msp, tls=tls, agent=None, - config_file=cfg + config_file=cfg, ) node.save() @@ -175,13 +183,18 @@ def _conversion_msp_tls_cfg(self, type, org, node): """ try: if type == "peer": - dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/" \ - .format(CELLO_HOME, org, org, node + "." + org) + dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/".format( + CELLO_HOME, org, org, node + "." + org + ) name = "core.yaml" cname = "peer_config.zip" else: - dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/" \ - .format(CELLO_HOME, org, org.split(".", 1)[1], node + "." + org.split(".", 1)[1]) + dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/".format( + CELLO_HOME, + org, + org.split(".", 1)[1], + node + "." + org.split(".", 1)[1], + ) name = "orderer.yaml" cname = "orderer_config.zip" @@ -193,8 +206,9 @@ def _conversion_msp_tls_cfg(self, type, org, node): with open("{}tls.zip".format(dir_node), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) - zip_file("{}{}".format(dir_node, name), - "{}{}".format(dir_node, cname)) + zip_file( + "{}{}".format(dir_node, name), "{}{}".format(dir_node, cname) + ) with open("{}{}".format(dir_node, cname), "rb") as f_cfg: cfg = base64.b64encode(f_cfg.read()) except Exception as e: @@ -219,9 +233,15 @@ def _generate_config(self, type, org, node): args.update({"peer_id": "{}.{}".format(node, org)}) args.update({"peer_address": "{}.{}:{}".format(node, org, 7051)}) args.update( - {"peer_gossip_externalEndpoint": "{}.{}:{}".format(node, org, 7051)}) + { + "peer_gossip_externalEndpoint": "{}.{}:{}".format( + node, org, 7051 + ) + } + ) args.update( - {"peer_chaincodeAddress": "{}.{}:{}".format(node, org, 7052)}) + {"peer_chaincodeAddress": "{}.{}:{}".format(node, org, 7052)} + ) args.update({"peer_tls_enabled": True}) args.update({"peer_localMspId": "{}MSP".format(org.capitalize())}) @@ -230,7 +250,8 @@ def _generate_config(self, type, org, node): else: args.update({"General_ListenPort": 7050}) args.update( - {"General_LocalMSPID": "{}OrdererMSP".format(org.capitalize())}) + {"General_LocalMSPID": "{}OrdererMSP".format(org.capitalize())} + ) args.update({"General_TLS_Enabled": True}) a = NodeConfig(org) @@ -245,8 +266,9 @@ def _conversion_msp_tls(self, name): :rtype: bytes """ try: - dir_org = "{}/{}/crypto-config/peerOrganizations/{}/" \ - .format(CELLO_HOME, name, name) + dir_org = "{}/{}/crypto-config/peerOrganizations/{}/".format( + CELLO_HOME, name, name + ) zip_dir("{}msp".format(dir_org), "{}msp.zip".format(dir_org)) with open("{}msp.zip".format(dir_org), "rb") as f_msp: diff --git a/src/api-engine/api/routes/user/views.py b/src/api-engine/api/routes/user/views.py index f259be063..b761f8925 100644 --- a/src/api-engine/api/routes/user/views.py +++ b/src/api-engine/api/routes/user/views.py @@ -19,7 +19,7 @@ UserIDSerializer, UserQuerySerializer, UserListSerializer, - UserUpdateSerializer + UserUpdateSerializer, ) from api.utils.common import with_common_response @@ -151,11 +151,16 @@ def attributes(self, request, pk=None): @swagger_auto_schema( method="post", request_body=UserUpdateSerializer, - responses=with_common_response( - {status.HTTP_200_OK: "OK"} - ) + responses=with_common_response({status.HTTP_200_OK: "OK"}), + ) + @action( + methods=["post"], + detail=True, + url_path="password", + permission_classes=[ + IsAuthenticated, + ], ) - @action(methods=["post"], detail=True, url_path="password", permission_classes=[IsAuthenticated, ]) def password(self, request, pk=None): """ post: diff --git a/src/api-engine/api/utils/__init__.py b/src/api-engine/api/utils/__init__.py index b5bc02767..1f4b2081e 100644 --- a/src/api-engine/api/utils/__init__.py +++ b/src/api-engine/api/utils/__init__.py @@ -25,9 +25,9 @@ def custom_exception_handler(exc, context): ): if isinstance(exc, ValidationError): response.data["code"] = ErrorCode.ValidationError.value - response.data[ - "detail" - ] = ErrorCode.ValidationError.display_string + response.data["detail"] = ( + ErrorCode.ValidationError.display_string + ) elif isinstance(exc, ParseError): response.data["code"] = ErrorCode.ParseError.value response.data["detail"] = ErrorCode.ParseError.display_string diff --git a/src/api-engine/api/utils/common.py b/src/api-engine/api/utils/common.py index 2d3f434ed..bc8c4f25a 100644 --- a/src/api-engine/api/utils/common.py +++ b/src/api-engine/api/utils/common.py @@ -91,7 +91,7 @@ def to_form_paras(self): def any_of(*perm_classes): """Returns permission class that allows access for - one of permission classes provided in perm_classes""" + one of permission classes provided in perm_classes""" class Or(BasePermission): def has_permission(*args): @@ -119,14 +119,16 @@ def zip_dir(dirpath, outFullName): dir_dst = "/" + dirpath.rsplit("/", 1)[1] zdir = ZipFile(outFullName, "w") for path, dirnames, filenames in os.walk(dirpath): - fpath = dir_dst + path.replace(dirpath, '') + fpath = dir_dst + path.replace(dirpath, "") for filename in filenames: - zdir.write(os.path.join(path, filename), - os.path.join(fpath, filename)) + zdir.write( + os.path.join(path, filename), os.path.join(fpath, filename) + ) # zip empty folder for dirname in dirnames: - zdir.write(os.path.join(path, dirname), - os.path.join(fpath, dirname)) + zdir.write( + os.path.join(path, dirname), os.path.join(fpath, dirname) + ) zdir.close() @@ -152,7 +154,13 @@ def parse_block_file(data): """ config = loads(data) if config.get("data"): - return config.get("data").get("data")[0].get("payload").get("data").get("config") + return ( + config.get("data") + .get("data")[0] + .get("payload") + .get("data") + .get("config") + ) return {"error": "can't find channel config"} @@ -173,25 +181,25 @@ def json_filter(input, output, expression): """ # if json_data is a file path, read the file if isinstance(input, str): - with open(input, 'r', encoding='utf-8') as f: + with open(input, "r", encoding="utf-8") as f: data = json.load(f) else: data = input # parse the path expression - path_parts = expression.strip('.').split('.') + path_parts = expression.strip(".").split(".") result = data for part in path_parts: # handle array index, like data[0] - if '[' in part and ']' in part: - array_name = part.split('[')[0] - index = int(part.split('[')[1].split(']')[0]) + if "[" in part and "]" in part: + array_name = part.split("[")[0] + index = int(part.split("[")[1].split("]")[0]) result = result[array_name][index] else: result = result[part] - with open(output, 'w', encoding='utf-8') as f: + with open(output, "w", encoding="utf-8") as f: json.dump(result, f, sort_keys=False, indent=4) LOG.info("jq {} {} -> {}".format(expression, input, output)) @@ -208,7 +216,7 @@ def json_add_anchor_peer(input, output, anchor_peer_config, org_msp): """ # if json_data is a file path, read the file if isinstance(input, str): - with open(input, 'r', encoding='utf-8') as f: + with open(input, "r", encoding="utf-8") as f: data = json.load(f) else: data = input @@ -218,14 +226,22 @@ def json_add_anchor_peer(input, output, anchor_peer_config, org_msp): if "Application" not in data["channel_group"]["groups"]: data["channel_group"]["groups"]["Application"] = {"groups": {}} if org_msp not in data["channel_group"]["groups"]["Application"]["groups"]: - data["channel_group"]["groups"]["Application"]["groups"][org_msp] = {"values": {}} + data["channel_group"]["groups"]["Application"]["groups"][org_msp] = { + "values": {} + } - data["channel_group"]["groups"]["Application"]["groups"][org_msp]["values"].update(anchor_peer_config) + data["channel_group"]["groups"]["Application"]["groups"][org_msp][ + "values" + ].update(anchor_peer_config) - with open(output, 'w', encoding='utf-8') as f: + with open(output, "w", encoding="utf-8") as f: json.dump(data, f, sort_keys=False, indent=4) - LOG.info("jq '.channel_group.groups.Application.groups.Org1MSP.values += ... ' {} -> {}".format(input, output)) + LOG.info( + "jq '.channel_group.groups.Application.groups.Org1MSP.values += ... ' {} -> {}".format( + input, output + ) + ) def json_create_envelope(input, output, channel): @@ -239,26 +255,21 @@ def json_create_envelope(input, output, channel): """ try: # Read the config update file - with open(input, 'r', encoding='utf-8') as f: + with open(input, "r", encoding="utf-8") as f: config_update = json.load(f) # Create the envelope structure envelope = { "payload": { "header": { - "channel_header": { - "channel_id": channel, - "type": 2 - } + "channel_header": {"channel_id": channel, "type": 2} }, - "data": { - "config_update": config_update - } + "data": {"config_update": config_update}, } } # Write the envelope to output file - with open(output, 'w', encoding='utf-8') as f: + with open(output, "w", encoding="utf-8") as f: json.dump(envelope, f, sort_keys=False, indent=4) LOG.info("echo 'payload ... ' | jq . > {}".format(output)) @@ -278,28 +289,46 @@ def init_env_vars(node, org): org_name = org.name org_domain = org_name.split(".", 1)[1] dir_certificate = "{}/{}/crypto-config/ordererOrganizations/{}".format( - CELLO_HOME, org_name, org_domain) + CELLO_HOME, org_name, org_domain + ) dir_node = "{}/{}/crypto-config/peerOrganizations".format( - CELLO_HOME, org_name) + CELLO_HOME, org_name + ) envs = {} - if (node.type == "orderer"): + if node.type == "orderer": envs = { "CORE_PEER_TLS_ENABLED": "true", - "ORDERER_CA": "{}/orderers/{}/msp/tlscacerts/tlsca.{}-cert.pem".format(dir_certificate, node.name + "." + org_domain, org_domain), - "ORDERER_ADMIN_TLS_SIGN_CERT": "{}/orderers/{}/tls/server.crt".format(dir_certificate, node.name + "." + org_domain), - "ORDERER_ADMIN_TLS_PRIVATE_KEY": "{}/orderers/{}/tls/server.key".format(dir_certificate, node.name + "." + org_domain) + "ORDERER_CA": "{}/orderers/{}/msp/tlscacerts/tlsca.{}-cert.pem".format( + dir_certificate, node.name + "." + org_domain, org_domain + ), + "ORDERER_ADMIN_TLS_SIGN_CERT": "{}/orderers/{}/tls/server.crt".format( + dir_certificate, node.name + "." + org_domain + ), + "ORDERER_ADMIN_TLS_PRIVATE_KEY": "{}/orderers/{}/tls/server.key".format( + dir_certificate, node.name + "." + org_domain + ), } - elif (node.type == "peer"): + + elif node.type == "peer": envs = { "CORE_PEER_TLS_ENABLED": "true", - "CORE_PEER_LOCALMSPID": "{}MSP".format(org_name.split(".")[0].capitalize()), - "CORE_PEER_TLS_ROOTCERT_FILE": "{}/{}/peers/{}/tls/ca.crt".format(dir_node, org_name, node.name + "." + org_name), - "CORE_PEER_MSPCONFIGPATH": "{}/{}/users/Admin@{}/msp".format(dir_node, org_name, org_name), + "CORE_PEER_LOCALMSPID": "{}MSP".format( + org_name.split(".")[0].capitalize() + ), + "CORE_PEER_TLS_ROOTCERT_FILE": "{}/{}/peers/{}/tls/ca.crt".format( + dir_node, org_name, node.name + "." + org_name + ), + "CORE_PEER_MSPCONFIGPATH": "{}/{}/users/Admin@{}/msp".format( + dir_node, org_name, org_name + ), "CORE_PEER_ADDRESS": "{}:{}".format( - node.name + "." + org_name, str(7051)), - "FABRIC_CFG_PATH": "{}/{}/peers/{}/".format(dir_node, org_name, node.name + "." + org_name) + node.name + "." + org_name, str(7051) + ), + "FABRIC_CFG_PATH": "{}/{}/peers/{}/".format( + dir_node, org_name, node.name + "." + org_name + ), } return envs diff --git a/src/api-engine/api/utils/jwt.py b/src/api-engine/api/utils/jwt.py index ab32ab859..b945e4104 100644 --- a/src/api-engine/api/utils/jwt.py +++ b/src/api-engine/api/utils/jwt.py @@ -31,7 +31,9 @@ def jwt_response_payload_handler(token, user=None, request=None): :param request: request context :return: UserSerializer data """ - return ok({ - "token": token, - "user": UserSerializer(user, context={"request": request}).data, - }) + return ok( + { + "token": token, + "user": UserSerializer(user, context={"request": request}).data, + } + ) diff --git a/src/api-engine/api/utils/node_config.py b/src/api-engine/api/utils/node_config.py index 101a6e5fe..100295e4c 100644 --- a/src/api-engine/api/utils/node_config.py +++ b/src/api-engine/api/utils/node_config.py @@ -10,7 +10,13 @@ class NodeConfig: """Class represents crypto-config yaml.""" - def __init__(self, org, peer_file="core.yaml", orderer_file="orderer.yaml", ca_file=""): + def __init__( + self, + org, + peer_file="core.yaml", + orderer_file="orderer.yaml", + ca_file="", + ): """ init node config @@ -41,7 +47,7 @@ def _render(src, dst, **kw): :rtype: none """ try: - with open(src, 'r+') as f: + with open(src, "r+") as f: cfg = yaml.load(f, Loader=yaml.FullLoader) for key, value in kw.items(): @@ -60,7 +66,7 @@ def _render(src, dst, **kw): elif len(keys) == 5: cfg[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]] = value - with open(dst, 'w+') as f: + with open(dst, "w+") as f: yaml.dump(cfg, f) except Exception as e: raise Exception("Configuration File Not Generated") from e @@ -75,11 +81,18 @@ def __from_dst(self, node, node_type): :rtype: string """ if node_type == "peer": - dst = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}.{}/{}"\ - .format(CELLO_HOME, self.org, self.org, node, self.org, self.peer_file) + dst = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}.{}/{}".format( + CELLO_HOME, self.org, self.org, node, self.org, self.peer_file + ) elif node_type == "orderer": - dst = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/{}"\ - .format(CELLO_HOME, self.org, self.org.split(".", 1)[1], node, self.org.split(".", 1)[1], self.orderer_file) + dst = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}.{}/{}".format( + CELLO_HOME, + self.org, + self.org.split(".", 1)[1], + node, + self.org.split(".", 1)[1], + self.orderer_file, + ) else: dst = "" return dst diff --git a/src/api-engine/api/utils/port_picker.py b/src/api-engine/api/utils/port_picker.py index 4aa42e0f6..4d422c335 100644 --- a/src/api-engine/api/utils/port_picker.py +++ b/src/api-engine/api/utils/port_picker.py @@ -120,11 +120,7 @@ def get_available_ports( used_ports = agent.free_ports ports = sample( - [ - i - for i in range(CLUSTER_PORT_START, 65535) - if i not in used_ports - ], + [i for i in range(CLUSTER_PORT_START, 65535) if i not in used_ports], request_count, ) diff --git a/src/api-engine/api/validators.py b/src/api-engine/api/validators.py index e87eeb0e5..5b436e8fc 100644 --- a/src/api-engine/api/validators.py +++ b/src/api-engine/api/validators.py @@ -17,7 +17,9 @@ def validate_url(value): parsed = urlparse(value) scheme, host = parsed.scheme, parsed.hostname or "" if scheme not in ("http", "https"): - raise ValidationError("Invalid scheme. URLs must start with 'http' or 'https'") + raise ValidationError( + "Invalid scheme. URLs must start with 'http' or 'https'" + ) fqdn = FQDN(host, min_labels=1) if not fqdn.is_valid: raise ValidationError("Invalid hostname") diff --git a/src/api-engine/api_engine/urls.py b/src/api-engine/api_engine/urls.py index dc35e309d..f05bc4991 100644 --- a/src/api-engine/api_engine/urls.py +++ b/src/api-engine/api_engine/urls.py @@ -79,9 +79,11 @@ urlpatterns = router.urls urlpatterns += [ - path('login', CelloTokenObtainPairView.as_view(), name='token_obtain_pair'), - path('login/refresh/', TokenRefreshView.as_view(), name='token_refresh'), - path('token-verify', CelloTokenVerifyView.as_view(), name='token_verify'), + path( + "login", CelloTokenObtainPairView.as_view(), name="token_obtain_pair" + ), + path("login/refresh/", TokenRefreshView.as_view(), name="token_refresh"), + path("token-verify", CelloTokenVerifyView.as_view(), name="token_verify"), path("docs/", SchemaView.with_ui("swagger", cache_timeout=0), name="docs"), path("redoc/", SchemaView.with_ui("redoc", cache_timeout=0), name="redoc"), ]