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
6from collections import OrderedDict
7from knack.log import get_logger
8
9
10logger = get_logger(__name__)
11
12
13def registry_output_format(result):
14    return _output_format(result, _registry_format_group)
15
16
17def usage_output_format(result):
18    return _output_format(result, _usage_format_group)
19
20
21def policy_output_format(result):
22    return _output_format(result, _policy_format_group)
23
24
25def credential_output_format(result):
26    return _output_format(result, _credential_format_group)
27
28
29def webhook_output_format(result):
30    return _output_format(result, _webhook_format_group)
31
32
33def webhook_get_config_output_format(result):
34    return _output_format(result, _webhook_get_config_format_group)
35
36
37def webhook_list_events_output_format(result):
38    return _output_format(result, _webhook_list_events_format_group)
39
40
41def webhook_ping_output_format(result):
42    return _output_format(result, _webhook_ping_format_group)
43
44
45def replication_output_format(result):
46    return _output_format(result, _replication_format_group)
47
48
49def task_output_format(result):
50    return _output_format(result, _task_format_group)
51
52
53def build_output_format(result):
54    return _output_format(result, _build_format_group)
55
56
57def run_output_format(result):
58    return _output_format(result, _run_format_group)
59
60
61def helm_list_output_format(result):
62    if isinstance(result, dict):
63        obj_list = []
64        for _, item in result.items():
65            obj_list += item
66        return _output_format(obj_list, _helm_format_group)
67    logger.debug("Unexpected output %s", result)
68    return _output_format(result, _helm_format_group)
69
70
71def helm_show_output_format(result):
72    return _output_format(result, _helm_format_group)
73
74
75def _output_format(result, format_group):
76    if 'value' in result and isinstance(result['value'], list):
77        result = result['value']
78    obj_list = result if isinstance(result, list) else [result]
79    return [format_group(item) for item in obj_list]
80
81
82def _registry_format_group(item):
83    return OrderedDict([
84        ('NAME', _get_value(item, 'name')),
85        ('RESOURCE GROUP', _get_value(item, 'resourceGroup')),
86        ('LOCATION', _get_value(item, 'location')),
87        ('SKU', _get_value(item, 'sku', 'name')),
88        ('LOGIN SERVER', _get_value(item, 'loginServer')),
89        ('CREATION DATE', _format_datetime(_get_value(item, 'creationDate'))),
90        ('ADMIN ENABLED', _get_value(item, 'adminUserEnabled'))
91    ])
92
93
94def _usage_format_group(item):
95    return OrderedDict([
96        ('NAME', _get_value(item, 'name')),
97        ('LIMIT', _get_value(item, 'limit')),
98        ('CURRENT VALUE', _get_value(item, 'currentValue')),
99        ('UNIT', _get_value(item, 'unit'))
100    ])
101
102
103def _policy_format_group(item):
104    return OrderedDict([
105        ('STATUS', _get_value(item, 'status')),
106        ('TYPE', _get_value(item, 'type'))
107    ])
108
109
110def _credential_format_group(item):
111    return OrderedDict([
112        ('USERNAME', _get_value(item, 'username')),
113        ('PASSWORD', _get_value(item, 'passwords', 0, 'value')),
114        ('PASSWORD2', _get_value(item, 'passwords', 1, 'value'))
115    ])
116
117
118def _webhook_format_group(item):
119    return OrderedDict([
120        ('NAME', _get_value(item, 'name')),
121        ('LOCATION', _get_value(item, 'location')),
122        ('ACTIONS', _get_value(item, 'actions')),
123        ('SCOPE', _get_value(item, 'scope')),
124        ('STATUS', _get_value(item, 'status'))
125    ])
126
127
128def _webhook_get_config_format_group(item):
129    return OrderedDict([
130        ('SERVICE URI', _get_value(item, 'serviceUri')),
131        ('HEADERS', _get_value(item, 'customHeaders'))
132    ])
133
134
135def _webhook_list_events_format_group(item):
136    repository = _get_value(item, 'eventRequestMessage', 'content', 'target', 'repository').strip()
137    tag = _get_value(item, 'eventRequestMessage', 'content', 'target', 'tag').strip()
138    status = _get_value(item, 'eventResponseMessage', 'statusCode').strip()
139    reason = _get_value(item, 'eventResponseMessage', 'reasonPhrase').strip()
140
141    return OrderedDict([
142        ('ID', _get_value(item, 'id')),
143        ('ACTION', _get_value(item, 'eventRequestMessage', 'content', 'action')),
144        ('IMAGE', '{}:{}'.format(repository, tag) if repository and tag else repository or ' '),
145        ('HTTP STATUS', '{} {}'.format(status, reason) if status and reason else status or reason or ' '),
146        ('TIMESTAMP', _format_datetime(_get_value(item, 'eventRequestMessage', 'content', 'timestamp')))
147    ])
148
149
150def _webhook_ping_format_group(item):
151    return OrderedDict([
152        ('ID', _get_value(item, 'id'))
153    ])
154
155
156def _replication_format_group(item):
157    return OrderedDict([
158        ('NAME', _get_value(item, 'name')),
159        ('LOCATION', _get_value(item, 'location')),
160        ('PROVISIONING STATE', _get_value(item, 'provisioningState')),
161        ('STATUS', _get_value(item, 'status', 'displayStatus'))
162    ])
163
164
165def _task_format_group(item):
166    return OrderedDict([
167        ('NAME', _get_value(item, 'name')),
168        ('PLATFORM', _get_value(item, 'platform', 'os')),
169        ('STATUS', _get_value(item, 'status')),
170        ('SOURCE REPOSITORY', _get_value(item, 'step', 'contextPath')),
171        ('SOURCE TRIGGER', _get_value(item, 'trigger', 'sourceTriggers', 0, 'status')),
172        ('BASE IMAGE TRIGGER', _get_value(item, 'trigger', 'baseImageTrigger', 'baseImageTriggerType'))
173    ])
174
175
176def _build_format_group(item):
177    return OrderedDict([
178        ('BUILD ID', _get_value(item, 'buildId')),
179        ('TASK', _get_value(item, 'buildTask')),
180        ('PLATFORM', _get_value(item, 'platform', 'osType')),
181        ('STATUS', _get_value(item, 'status')),
182        ("TRIGGER", _get_build_trigger(_get_value(item, 'imageUpdateTrigger'),
183                                       _get_value(item, 'sourceTrigger', 'eventType'))),
184        ('STARTED', _format_datetime(_get_value(item, 'startTime'))),
185        ('DURATION', _get_duration(_get_value(item, 'startTime'), _get_value(item, 'finishTime')))
186    ])
187
188
189def _run_format_group(item):
190    return OrderedDict([
191        ('RUN ID', _get_value(item, 'runId')),
192        ('TASK', _get_value(item, 'task')),
193        ('PLATFORM', _get_value(item, 'platform', 'os')),
194        ('STATUS', _get_value(item, 'status')),
195        ("TRIGGER", _get_build_trigger(_get_value(item, 'imageUpdateTrigger'),
196                                       _get_value(item, 'sourceTrigger', 'eventType'))),
197        ('STARTED', _format_datetime(_get_value(item, 'startTime'))),
198        ('DURATION', _get_duration(_get_value(item, 'startTime'), _get_value(item, 'finishTime')))
199    ])
200
201
202def _helm_format_group(item):
203    description = _get_value(item, 'description')
204    if len(description) > 57:  # Similar to helm client
205        description = description[:57] + '...'
206
207    return OrderedDict([
208        ('NAME', _get_value(item, 'name')),
209        ('CHART VERSION', _get_value(item, 'version')),
210        ('APP VERSION', _get_value(item, 'appVersion')),
211        ('DESCRIPTION', description)
212    ])
213
214
215def _get_value(item, *args):
216    """Get a nested value from a dict.
217    :param dict item: The dict object
218    """
219    try:
220        for arg in args:
221            item = item[arg]
222        return str(item) if item else ' '
223    except (KeyError, TypeError, IndexError):
224        return ' '
225
226
227def _get_build_trigger(image_update_trigger, git_source_trigger):
228    if git_source_trigger.strip():
229        return git_source_trigger
230    if image_update_trigger.strip():
231        return 'Image Update'
232    return 'Manual'
233
234
235def _format_datetime(date_string):
236    from dateutil.parser import parse
237    try:
238        return parse(date_string).strftime("%Y-%m-%dT%H:%M:%SZ")
239    except ValueError:
240        logger.debug("Unable to parse date_string '%s'", date_string)
241        return date_string or ' '
242
243
244def _get_duration(start_time, finish_time):
245    from dateutil.parser import parse
246    try:
247        duration = parse(finish_time) - parse(start_time)
248        hours = "{0:02d}".format((24 * duration.days) + (duration.seconds // 3600))
249        minutes = "{0:02d}".format((duration.seconds % 3600) // 60)
250        seconds = "{0:02d}".format(duration.seconds % 60)
251        return "{0}:{1}:{2}".format(hours, minutes, seconds)
252    except ValueError:
253        logger.debug("Unable to get duration with start_time '%s' and finish_time '%s'", start_time, finish_time)
254        return ' '
255