Completed
Pull Request — master (#2631)
by Lakshmi
05:51
created

KeyValuePairGetCommand.__init__()   A

Complexity

Conditions 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 4
rs 10
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
import os
17
import json
18
import logging
19
from os.path import join as pjoin
20
21
from st2client.commands import resource
22
from st2client.commands.noop import NoopCommand
23
from st2client.commands.resource import add_auth_token_to_kwargs_from_cli
24
from st2client.formatters import table
25
from st2client.models.keyvalue import KeyValuePair
26
from st2client.utils.date import format_isodate_for_user_timezone
27
28
LOG = logging.getLogger(__name__)
29
30
31
class KeyValuePairBranch(resource.ResourceBranch):
32
33
    def __init__(self, description, app, subparsers, parent_parser=None):
34
        super(KeyValuePairBranch, self).__init__(
35
            KeyValuePair, description, app, subparsers,
36
            parent_parser=parent_parser,
37
            commands={
38
                'list': KeyValuePairListCommand,
39
                'get': KeyValuePairGetCommand,
40
                'delete': KeyValuePairDeleteCommand,
41
                'create': NoopCommand,
42
                'update': NoopCommand
43
            })
44
45
        # Registers extended commands
46
        self.commands['set'] = KeyValuePairSetCommand(self.resource, self.app,
47
                                                      self.subparsers)
48
        self.commands['load'] = KeyValuePairLoadCommand(
49
            self.resource, self.app, self.subparsers)
50
        self.commands['delete_by_prefix'] = KeyValuePairDeleteByPrefixCommand(
51
            self.resource, self.app, self.subparsers)
52
53
        # Remove unsupported commands
54
        # TODO: Refactor parent class and make it nicer
55
        del self.commands['create']
56
        del self.commands['update']
57
58
59
class KeyValuePairListCommand(resource.ResourceListCommand):
60
    display_attributes = ['name', 'value', 'expire_timestamp']
61
    attribute_transform_functions = {
62
        'expire_timestamp': format_isodate_for_user_timezone,
63
    }
64
65
    def __init__(self, *args, **kwargs):
66
        super(KeyValuePairListCommand, self).__init__(*args, **kwargs)
67
68
        # Filter options
69
        self.parser.add_argument('--prefix', help=('Only return values which name starts with the '
70
                                                   ' provided prefix.'))
71
72
    def run_and_print(self, args, **kwargs):
73
        if args.prefix:
74
            kwargs['prefix'] = args.prefix
75
76
        instances = self.run(args, **kwargs)
77
        self.print_output(reversed(instances), table.MultiColumnTable,
78
                          attributes=args.attr, widths=args.width,
79
                          json=args.json,
80
                          attribute_transform_functions=self.attribute_transform_functions)
81
82
83
class KeyValuePairGetCommand(resource.ResourceGetCommand):
84
    pk_argument_name = 'name'
85
    display_attributes = ['name', 'value', 'secret', 'encrypted', 'expire_timestamp']
86
87
    def __init__(self, kv_resource, *args, **kwargs):
88
        super(KeyValuePairGetCommand, self).__init__(kv_resource, *args, **kwargs)
89
        self.parser.add_argument('-d', '--decrypt', action='store_true',
90
                                 help='Decrypt secret if encrypted.')
91
92
    @resource.add_auth_token_to_kwargs_from_cli
93
    def run(self, args, **kwargs):
94
        resource_name = getattr(args, self.pk_argument_name, None)
95
        decrypt = getattr(args, 'decrypt', False)
96
        kwargs['params'] = {}
97
        kwargs['params']['decrypt'] = str(decrypt).lower()
98
        return self.get_resource_by_id(id=resource_name, **kwargs)
99
100
101
class KeyValuePairSetCommand(resource.ResourceCommand):
102
    display_attributes = ['name', 'value', 'expire_timestamp']
103
104
    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 21).

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...
105
        super(KeyValuePairSetCommand, self).__init__(
106
            resource, 'set',
107
            'Set an existing %s.' % resource.get_display_name().lower(),
108
            *args, **kwargs
109
        )
110
111
        self.parser.add_argument('name',
112
                                 metavar='name',
113
                                 help='Name of the key value pair.')
114
        self.parser.add_argument('value', help='Value paired with the key.')
115
        self.parser.add_argument('-l', '--ttl', dest='ttl', type=int, default=None,
116
                                 help='TTL (in seconds) for this value.')
117
        self.parser.add_argument('-e', '--encrypt', dest='secret',
118
                                 action='store_true',
119
                                 help='Encrypt value before saving the value.')
120
121
    @add_auth_token_to_kwargs_from_cli
122
    def run(self, args, **kwargs):
123
        instance = KeyValuePair()
124
        instance.id = args.name  # TODO: refactor and get rid of id
125
        instance.name = args.name
126
        instance.value = args.value
127
128
        if args.secret:
129
            instance.secret = args.secret
130
131
        if args.ttl:
132
            instance.ttl = args.ttl
133
134
        return self.manager.update(instance, **kwargs)
135
136
    def run_and_print(self, args, **kwargs):
137
        instance = self.run(args, **kwargs)
138
        self.print_output(instance, table.PropertyValueTable,
139
                          attributes=self.display_attributes, json=args.json)
140
141
142
class KeyValuePairDeleteCommand(resource.ResourceDeleteCommand):
143
    pk_argument_name = 'name'
144
145
    @add_auth_token_to_kwargs_from_cli
146
    def run(self, args, **kwargs):
147
        resource_id = getattr(args, self.pk_argument_name, None)
148
        instance = self.get_resource(resource_id, **kwargs)
149
150
        if not instance:
151
            raise resource.ResourceNotFoundError('KeyValuePair with id "%s" not found', resource_id)
152
153
        instance.id = resource_id  # TODO: refactor and get rid of id
154
        self.manager.delete(instance, **kwargs)
155
156
157
class KeyValuePairDeleteByPrefixCommand(resource.ResourceCommand):
158
    """
159
    Commands which delete all the key value pairs which match the provided
160
    prefix.
161
    """
162
    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 21).

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...
163
        super(KeyValuePairDeleteByPrefixCommand, self).__init__(resource, 'delete_by_prefix',
164
            'Delete KeyValue pairs which match the provided prefix', *args, **kwargs)
165
166
        self.parser.add_argument('-p', '--prefix', required=True,
167
                                 help='Name prefix (e.g. twitter.TwitterSensor:)')
168
169
    @add_auth_token_to_kwargs_from_cli
170
    def run(self, args, **kwargs):
171
        prefix = args.prefix
172
        key_pairs = self.manager.get_all(prefix=prefix)
173
174
        to_delete = []
175
        for key_pair in key_pairs:
176
            key_pair.id = key_pair.name
177
            to_delete.append(key_pair)
178
179
        deleted = []
180
        for key_pair in to_delete:
181
            self.manager.delete(instance=key_pair, **kwargs)
182
            deleted.append(key_pair)
183
184
        return deleted
185
186
    def run_and_print(self, args, **kwargs):
187
        # TODO: Need to use args, instead of kwargs (args=) because of bad API
188
        # FIX ME
189
        deleted = self.run(args, **kwargs)
190
        key_ids = [key_pair.id for key_pair in deleted]
191
192
        print('Deleted %s keys' % (len(deleted)))
193
        print('Deleted key ids: %s' % (', '.join(key_ids)))
194
195
196
class KeyValuePairLoadCommand(resource.ResourceCommand):
197
    pk_argument_name = 'name'
198
    display_attributes = ['name', 'value']
199
200
    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 21).

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...
201
        help_text = ('Load a list of %s from file.' %
202
                     resource.get_plural_display_name().lower())
203
        super(KeyValuePairLoadCommand, self).__init__(resource, 'load',
204
            help_text, *args, **kwargs)
205
206
        self.parser.add_argument(
207
            'file', help=('JSON file containing the %s to create.'
208
                          % resource.get_plural_display_name().lower()))
209
210
    @add_auth_token_to_kwargs_from_cli
211
    def run(self, args, **kwargs):
212
        file_path = os.path.normpath(pjoin(os.getcwd(), args.file))
213
214
        if not os.path.exists(args.file):
215
            raise ValueError('File "%s" doesn\'t exist' % (file_path))
216
217
        if not os.path.isfile(args.file):
218
            raise ValueError('"%s" is not a file' % (file_path))
219
220
        with open(file_path, 'r') as f:
221
            kvps = json.loads(f.read())
222
223
        instances = []
224
        for item in kvps:
225
            name = item['name']
226
            value = item['value']
227
228
            instance = KeyValuePair()
229
            instance.id = name  # TODO: refactor and get rid of id
230
            instance.name = name
231
            instance.value = value
232
233
            self.manager.update(instance, **kwargs)
234
            instances.append(instance)
235
        return instances
236
237
    def run_and_print(self, args, **kwargs):
238
        instances = self.run(args, **kwargs)
239
        self.print_output(instances, table.MultiColumnTable,
240
                          attributes=['id', 'name', 'value'], json=args.json)
241