1# --------------------------------------------------------------------------------------------
2# Copyright (c) Microsoft Corporation. All rights reserved.
3# Licensed under the MIT License. See License.txt in the project root for license information.
4# --------------------------------------------------------------------------------------------
5
6import json
7from collections import OrderedDict
8from knack.log import get_logger
9
10logger = get_logger(__name__)
11
12
13def configstore_output_format(result):
14    return _output_format(result, _configstore_format_group)
15
16
17def configstore_identity_format(result):
18    return _output_format(result, _configstore_identity_format_group)
19
20
21def configstore_credential_format(result):
22    return _output_format(result, _configstore_credential_format_group)
23
24
25def keyvalue_entry_format(result):
26    return _output_format(result, _keyvalue_entry_format_group)
27
28
29def featureflag_entry_format(result):
30    return _output_format(result, _featureflag_entry_format_group)
31
32
33def featurefilter_entry_format(result):
34    return _output_format(result, _featurefilter_entry_format_group)
35
36
37def _output_format(result, format_group):
38    if 'value' in result and isinstance(result['value'], list):
39        result = result['value']
40    obj_list = result if isinstance(result, list) else [result]
41    return [format_group(item) for item in obj_list]
42
43
44def _configstore_format_group(item):
45    sku_value = _get_value(item, 'sku')
46
47    try:
48        sku = json.loads(sku_value.replace("\'", "\"")).get('name')
49    except ValueError:
50        logger.debug("No valid sku %s found", sku_value)
51        sku = ""
52
53    return OrderedDict([
54        ('CREATION DATE', _format_datetime(_get_value(item, 'creationDate'))),
55        ('ENDPOINT', _get_value(item, 'endpoint')),
56        ('LOCATION', _get_value(item, 'location')),
57        ('NAME', _get_value(item, 'name')),
58        ('PROVISIONING STATE', _get_value(item, 'provisioningState')),
59        ('RESOURCE GROUP', _get_value(item, 'resourceGroup')),
60        ('SKU', sku)
61    ])
62
63
64def _configstore_identity_format_group(item):
65    return OrderedDict([
66        ('PRINCIPAL ID', _format_datetime(_get_value(item, 'principalId'))),
67        ('TENANT ID', _get_value(item, 'tenantId')),
68        ('TYPE', _get_value(item, 'type'))
69    ])
70
71
72def _configstore_credential_format_group(item):
73    return OrderedDict([
74        ('CONNECTION STRING', _get_value(item, 'connectionString')),
75        ('ID', _get_value(item, 'id')),
76        ('LAST MODIFIED', _format_datetime(_get_value(item, 'lastModified'))),
77        ('NAME', _get_value(item, 'name')),
78        ('READ ONLY', _get_value(item, 'readOnly')),
79        ('VALUE', _get_value(item, 'value'))
80    ])
81
82
83def _keyvalue_entry_format_group(item):
84    # CLI core converts KeyValue object field names to camelCase (eg: content_type becomes contentType)
85    # But when customers specify field filters, we return a dict of requested fields instead of KeyValue object
86    # In that case, field names are not converted to camelCase. We need to check for both content_type and contentType
87    content_type = _get_value(item, 'contentType')
88    content_type = content_type if content_type != ' ' else _get_value(item, 'content_type')
89
90    last_modified = _get_value(item, 'lastModified')
91    last_modified = last_modified if last_modified != ' ' else _get_value(item, 'last_modified')
92
93    return OrderedDict([
94        ('CONTENT TYPE', content_type),
95        ('KEY', _get_value(item, 'key')),
96        ('VALUE', _get_value(item, 'value')),
97        ('LAST MODIFIED', _format_datetime(last_modified)),
98        ('TAGS', _get_value(item, 'tags')),
99        ('LABEL', _get_value(item, 'label')),
100        ('LOCKED', _get_value(item, 'locked'))
101    ])
102
103
104def _featureflag_entry_format_group(item):
105    last_modified = _get_value(item, 'lastModified')
106    last_modified = last_modified if last_modified != ' ' else _get_value(item, 'last_modified')
107
108    return OrderedDict([
109        ('KEY', _get_value(item, 'key')),
110        ('LABEL', _get_value(item, 'label')),
111        ('STATE', _get_value(item, 'state')),
112        ('LOCKED', _get_value(item, 'locked')),
113        ('DESCRIPTION', _get_value(item, 'description')),
114        ('LAST MODIFIED', _format_datetime(last_modified)),
115        ('CONDITIONS', _get_value(item, 'conditions'))
116    ])
117
118
119def _featurefilter_entry_format_group(item):
120    return OrderedDict([
121        ('NAME', _get_value(item, 'name')),
122        ('PARAMETERS', _get_value(item, 'parameters'))
123    ])
124
125
126def _format_datetime(date_string):
127    from dateutil.parser import parse
128    try:
129        return parse(date_string).strftime("%Y-%m-%dT%H:%M:%SZ")
130    except ValueError:
131        return date_string or ' '
132
133
134def _get_value(item, *args):
135    """Recursively get a nested value from a dict.
136    :param dict item: The dict object
137    """
138    try:
139        for arg in args:
140            item = item[arg]
141        return _EvenLadder(item) if item is not None else ' '
142    except (KeyError, TypeError, IndexError):
143        return ' '
144
145
146def _EvenLadder(item):
147    formated_item = ''
148    item = str(item)
149    if len(item) < 70:
150        return item
151    for i in range(0, len(item), 70):
152        formated_item += str(item[i: i + 70]) + "\n"
153    return formated_item
154