github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/cli/sawtooth_cli/settings.py (about) 1 # Copyright 2017 Intel Corporation 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # ------------------------------------------------------------------------------ 15 16 from base64 import b64decode 17 import csv 18 import hashlib 19 import json 20 import sys 21 22 import yaml 23 24 from sawtooth_cli.exceptions import CliException 25 from sawtooth_cli.rest_client import RestClient 26 from sawtooth_cli import tty 27 28 from sawtooth_cli.protobuf.setting_pb2 import Setting 29 30 31 SETTINGS_NAMESPACE = '000000' 32 33 _MIN_PRINT_WIDTH = 15 34 _MAX_KEY_PARTS = 4 35 _ADDRESS_PART_SIZE = 16 36 37 38 def add_settings_parser(subparsers, parent_parser): 39 """Creates the args parser needed for the settings command and its 40 subcommands. 41 """ 42 # The following parser is for the settings subsection of commands. These 43 # commands display information about the currently applied on-chain 44 # settings. 45 46 settings_parser = subparsers.add_parser( 47 'settings', 48 help='Displays on-chain settings', 49 description='Displays the values of currently active on-chain ' 50 'settings.') 51 52 settings_parsers = settings_parser.add_subparsers( 53 title='settings', 54 dest='settings_cmd') 55 settings_parsers.required = True 56 57 list_parser = settings_parsers.add_parser( 58 'list', 59 help='Lists the current keys and values of on-chain settings', 60 description='List the current keys and values of on-chain ' 61 'settings. The content can be exported to various ' 62 'formats for external consumption.' 63 ) 64 65 list_parser.add_argument( 66 '--url', 67 type=str, 68 help="identify the URL of a validator's REST API", 69 default='http://localhost:8008') 70 71 list_parser.add_argument( 72 '--filter', 73 type=str, 74 default='', 75 help='filters keys that begin with this value') 76 77 list_parser.add_argument( 78 '--format', 79 default='default', 80 choices=['default', 'csv', 'json', 'yaml'], 81 help='choose the output format') 82 83 84 def do_settings(args): 85 if args.settings_cmd == 'list': 86 _do_settings_list(args) 87 else: 88 raise AssertionError('Invalid subcommand: ') 89 90 91 def _do_settings_list(args): 92 """Lists the current on-chain configuration values. 93 """ 94 rest_client = RestClient(args.url) 95 state = rest_client.list_state(subtree=SETTINGS_NAMESPACE) 96 97 prefix = args.filter 98 99 head = state['head'] 100 state_values = state['data'] 101 printable_settings = [] 102 proposals_address = _key_to_address('sawtooth.settings.vote.proposals') 103 for state_value in state_values: 104 if state_value['address'] == proposals_address: 105 # This is completely internal setting and we won't list it here 106 continue 107 108 decoded = b64decode(state_value['data']) 109 setting = Setting() 110 setting.ParseFromString(decoded) 111 112 for entry in setting.entries: 113 if entry.key.startswith(prefix): 114 printable_settings.append(entry) 115 116 printable_settings.sort(key=lambda s: s.key) 117 118 if args.format == 'default': 119 tty_width = tty.width() 120 for setting in printable_settings: 121 # Set value width to the available terminal space, or the min width 122 width = tty_width - len(setting.key) - 3 123 width = width if width > _MIN_PRINT_WIDTH else _MIN_PRINT_WIDTH 124 value = (setting.value[:width] + '...' 125 if len(setting.value) > width 126 else setting.value) 127 print('{}: {}'.format(setting.key, value)) 128 elif args.format == 'csv': 129 try: 130 writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL) 131 writer.writerow(['KEY', 'VALUE']) 132 for setting in printable_settings: 133 writer.writerow([setting.key, setting.value]) 134 except csv.Error: 135 raise CliException('Error writing CSV') 136 elif args.format == 'json' or args.format == 'yaml': 137 settings_snapshot = { 138 'head': head, 139 'settings': {setting.key: setting.value 140 for setting in printable_settings} 141 } 142 if args.format == 'json': 143 print(json.dumps(settings_snapshot, indent=2, sort_keys=True)) 144 else: 145 print(yaml.dump(settings_snapshot, default_flow_style=False)[0:-1]) 146 else: 147 raise AssertionError('Unknown format {}'.format(args.format)) 148 149 150 def _key_to_address(key): 151 """Creates the state address for a given setting key. 152 """ 153 key_parts = key.split('.', maxsplit=_MAX_KEY_PARTS - 1) 154 key_parts.extend([''] * (_MAX_KEY_PARTS - len(key_parts))) 155 156 return SETTINGS_NAMESPACE + ''.join(_short_hash(x) for x in key_parts) 157 158 159 def _short_hash(in_str): 160 return hashlib.sha256(in_str.encode()).hexdigest()[:_ADDRESS_PART_SIZE]