Completed
Pull Request — master (#2258)
by Manas
06:31 queued 01:12
created

st2client.commands.TraceGetCommand.__init__()   A

Complexity

Conditions 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4286
cc 1
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
from st2client.models import Resource, Trace, TriggerInstance, Rule, LiveAction
17
from st2client.exceptions.operations import OperationFailureException
18
from st2client.formatters import table
19
from st2client.formatters import execution as execution_formatter
20
from st2client.commands import resource
21
from st2client.utils.date import format_isodate
22
23
24
TRACE_ATTRIBUTE_DISPLAY_ORDER = ['id', 'trace_tag', 'action_executions', 'rules',
25
                                 'trigger_instances', 'start_timestamp']
26
27
TRACE_HEADER_DISPLAY_ORDER = ['id', 'trace_tag', 'start_timestamp']
28
29
TRACE_COMPONENT_DISPLAY_LABELS = ['id', 'type', 'updated_at']
30
31
TRACE_DISPLAY_ATTRIBUTES = ['all']
32
33
TRIGGER_INSTANCE_DISPLAY_OPTIONS = [
34
    'all',
35
    'trigger-instances',
36
    'trigger_instances',
37
    'triggerinstances',
38
    'triggers'
39
]
40
41
ACTION_EXECUTION_DISPLAY_OPTIONS = [
42
    'all',
43
    'executions',
44
    'action-executions',
45
    'action_executions',
46
    'actionexecutions',
47
    'actions'
48
]
49
50
51
class TraceBranch(resource.ResourceBranch):
52
    def __init__(self, description, app, subparsers, parent_parser=None):
53
        super(TraceBranch, self).__init__(
54
            Trace, description, app, subparsers,
55
            parent_parser=parent_parser,
56
            read_only=True,
57
            commands={
58
                'list': TraceListCommand,
59
                'get': TraceGetCommand
60
            })
61
62
63
class SingleTraceDisplayMixin(object):
64
65
    def print_trace_details(self, trace, args, **kwargs):
66
        options = {'attributes': TRACE_ATTRIBUTE_DISPLAY_ORDER if args.json else
67
                   TRACE_HEADER_DISPLAY_ORDER}
68
        options['json'] = args.json
69
        options['attribute_transform_functions'] = self.attribute_transform_functions
70
71
        formatter = execution_formatter.ExecutionResult
72
73
        self.print_output(trace, formatter, **options)
74
75
        # Everything should be printed if we are printing json.
76
        if args.json:
77
            return
78
79
        components = []
80
        if any(attr in args.attr for attr in TRIGGER_INSTANCE_DISPLAY_OPTIONS):
81
            components.extend([Resource(**{'id': trigger_instance['object_id'],
82
                                           'type': TriggerInstance._alias.lower(),
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _alias was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
83
                                           'updated_at': trigger_instance['updated_at']})
84
                               for trigger_instance in trace.trigger_instances])
85
        if any(attr in args.attr for attr in ['all', 'rules']):
86
            components.extend([Resource(**{'id': rule['object_id'],
87
                                           'type': Rule._alias.lower(),
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _alias was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
88
                                           'updated_at': rule['updated_at']})
89
                               for rule in trace.rules])
90
        if any(attr in args.attr for attr in ACTION_EXECUTION_DISPLAY_OPTIONS):
91
            components.extend([Resource(**{'id': execution['object_id'],
92
                                           'type': LiveAction._alias.lower(),
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _alias was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
93
                                           'updated_at': execution['updated_at']})
94
                               for execution in trace.action_executions])
95
        if components:
96
            components.sort(key=lambda resource: resource.updated_at)
97
            self.print_output(components, table.MultiColumnTable,
98
                              attributes=TRACE_COMPONENT_DISPLAY_LABELS,
99
                              json=args.json)
100
101
102
class TraceListCommand(resource.ResourceCommand, SingleTraceDisplayMixin):
103
    display_attributes = ['id', 'trace_tag', 'start_timestamp']
104
105
    attribute_transform_functions = {
106
        'start_timestamp': format_isodate
107
    }
108
109
    attribute_display_order = TRACE_ATTRIBUTE_DISPLAY_ORDER
110
111
    def __init__(self, resource, *args, **kwargs):
0 ignored issues
show
Comprehensibility Bug introduced by
resource is re-defining a name which is already available in the outer-scope (previously defined on line 20).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
112
        super(TraceListCommand, self).__init__(
113
            resource, 'list', 'Get the list of the 50 most recent %s.' %
114
            resource.get_plural_display_name().lower(),
115
            *args, **kwargs)
116
117
        self.group = self.parser.add_mutually_exclusive_group()
118
        self.parser.add_argument('-n', '--last', type=int, dest='last',
119
                                 default=50,
120
                                 help=('List N most recent %s; '
121
                                       'list all if 0.' %
122
                                       resource.get_plural_display_name().lower()))
123
124
        # Filter options
125
        self.group.add_argument('-c', '--trace-tag', help='Trace-tag to filter the list.')
126
        self.group.add_argument('-e', '--execution', help='Execution to filter the list.')
127
        self.group.add_argument('-r', '--rule', help='Rule to filter the list.')
128
        self.group.add_argument('-g', '--trigger-instance',
129
                                help='TriggerInstance to filter the list.')
130
        # Display options
131
        self.parser.add_argument('-a', '--attr', nargs='+',
132
                                 default=self.display_attributes,
133
                                 help=('List of attributes to include in the '
134
                                       'output. "all" will return all '
135
                                       'attributes.'))
136
        self.parser.add_argument('-w', '--width', nargs='+', type=int,
137
                                 default=None,
138
                                 help=('Set the width of columns in output.'))
139
140
    @resource.add_auth_token_to_kwargs_from_cli
141
    def run(self, args, **kwargs):
142
        # Filtering options
143
        if args.trace_tag:
144
            kwargs['trace_tag'] = args.trace_tag
145
        if args.trigger_instance:
146
            kwargs['trigger_instance'] = args.trigger_instance
147
        if args.execution:
148
            kwargs['execution'] = args.execution
149
        if args.rule:
150
            kwargs['rule'] = args.rule
151
152
        return self.manager.query(limit=args.last, **kwargs)
153
154
    def run_and_print(self, args, **kwargs):
155
        instances = self.run(args, **kwargs)
156
        if instances and len(instances) == 1:
157
            # For a single Trace we must include the components unless
158
            # user has overriden the attributes to display
159
            if args.attr == self.display_attributes:
160
                args.attr = ['all']
161
            self.print_trace_details(trace=instances[0], args=args)
162
        else:
163
            self.print_output(reversed(instances), table.MultiColumnTable,
164
                              attributes=args.attr, widths=args.width,
165
                              json=args.json,
166
                              attribute_transform_functions=self.attribute_transform_functions)
167
168
169
class TraceGetCommand(resource.ResourceGetCommand, SingleTraceDisplayMixin):
170
    display_attributes = ['all']
171
    attribute_display_order = TRACE_ATTRIBUTE_DISPLAY_ORDER
172
    attribute_transform_functions = {
173
        'start_timestamp': format_isodate
174
    }
175
176
    pk_argument_name = 'id'
177
178
    def __init__(self, resource, *args, **kwargs):
0 ignored issues
show
Comprehensibility Bug introduced by
resource is re-defining a name which is already available in the outer-scope (previously defined on line 20).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
179
        super(TraceGetCommand, self).__init__(resource, *args, **kwargs)
180
181
        self.group = self.parser.add_mutually_exclusive_group()
182
183
        # Causation chains
184
        self.group.add_argument('-e', '--execution', help='Execution to show causation chain.')
185
        self.group.add_argument('-r', '--rule', help='Rule to show causation chain.')
186
        self.group.add_argument('-g', '--trigger-instance',
187
                                help='TriggerInstance to show causation chain.')
188
189
    @resource.add_auth_token_to_kwargs_from_cli
190
    def run(self, args, **kwargs):
191
        resource_id = getattr(args, self.pk_argument_name, None)
192
        return self.get_resource_by_id(resource_id, **kwargs)
193
194
    @resource.add_auth_token_to_kwargs_from_cli
195
    def run_and_print(self, args, **kwargs):
196
        trace = None
197
        try:
198
            trace = self.run(args, **kwargs)
199
        except resource.ResourceNotFoundError:
200
            self.print_not_found(args.id)
201
            raise OperationFailureException('Trace %s not found.' % (args.id))
202
        return self.print_trace_details(trace=trace, args=args)
203