Passed
Push — develop ( f78e74...17ab74 )
by Plexxi
07:06 queued 03:26
created

KeyValuePairDeleteCommand.__init__()   A

Complexity

Conditions 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
c 2
b 0
f 0
dl 0
loc 8
rs 9.4285
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
DEFAULT_SCOPE = 'system'
31
32
33
class KeyValuePairBranch(resource.ResourceBranch):
34
35
    def __init__(self, description, app, subparsers, parent_parser=None):
36
        super(KeyValuePairBranch, self).__init__(
37
            KeyValuePair, description, app, subparsers,
38
            parent_parser=parent_parser,
39
            commands={
40
                'list': KeyValuePairListCommand,
41
                'get': KeyValuePairGetCommand,
42
                'delete': KeyValuePairDeleteCommand,
43
                'create': NoopCommand,
44
                'update': NoopCommand
45
            })
46
47
        # Registers extended commands
48
        self.commands['set'] = KeyValuePairSetCommand(self.resource, self.app,
49
                                                      self.subparsers)
50
        self.commands['load'] = KeyValuePairLoadCommand(
51
            self.resource, self.app, self.subparsers)
52
        self.commands['delete_by_prefix'] = KeyValuePairDeleteByPrefixCommand(
53
            self.resource, self.app, self.subparsers)
54
55
        # Remove unsupported commands
56
        # TODO: Refactor parent class and make it nicer
57
        del self.commands['create']
58
        del self.commands['update']
59
60
61
class KeyValuePairListCommand(resource.ResourceListCommand):
62
    display_attributes = ['name', 'value', 'secret', 'encrypted', 'scope', 'user',
63
                          'expire_timestamp']
64
    attribute_transform_functions = {
65
        'expire_timestamp': format_isodate_for_user_timezone,
66
    }
67
68
    def __init__(self, *args, **kwargs):
69
        super(KeyValuePairListCommand, self).__init__(*args, **kwargs)
70
71
        # Filter options
72
        self.parser.add_argument('--prefix', help=('Only return values which name starts with the '
73
                                                   ' provided prefix.'))
74
        self.parser.add_argument('--decrypt', action='store_true',
75
                                 help='Decrypt secrets and display plain text.')
76
        self.parser.add_argument('-s', '--scope', default='system', dest='scope',
77
                                 help='Scope item is under. Example: "user".')
78
79
    def run_and_print(self, args, **kwargs):
80
        if args.prefix:
81
            kwargs['prefix'] = args.prefix
82
83
        decrypt = getattr(args, 'decrypt', False)
84
        kwargs['params'] = {'decrypt': str(decrypt).lower()}
85
        scope = getattr(args, 'scope', DEFAULT_SCOPE)
86
        kwargs['params']['scope'] = scope
87
88
        instances = self.run(args, **kwargs)
89
        self.print_output(reversed(instances), table.MultiColumnTable,
90
                          attributes=args.attr, widths=args.width,
91
                          json=args.json,
92
                          yaml=args.yaml,
93
                          attribute_transform_functions=self.attribute_transform_functions)
94
95
96
class KeyValuePairGetCommand(resource.ResourceGetCommand):
97
    pk_argument_name = 'name'
98
    display_attributes = ['name', 'value', 'secret', 'encrypted', 'scope', 'expire_timestamp']
99
100
    def __init__(self, kv_resource, *args, **kwargs):
101
        super(KeyValuePairGetCommand, self).__init__(kv_resource, *args, **kwargs)
102
        self.parser.add_argument('-d', '--decrypt', action='store_true',
103
                                 help='Decrypt secret if encrypted and show plain text.')
104
        self.parser.add_argument('-s', '--scope', default=DEFAULT_SCOPE, dest='scope',
105
                                 help='Scope item is under. Example: "user".')
106
107
    @resource.add_auth_token_to_kwargs_from_cli
108
    def run(self, args, **kwargs):
109
        resource_name = getattr(args, self.pk_argument_name, None)
110
        decrypt = getattr(args, 'decrypt', False)
111
        scope = getattr(args, 'scope', DEFAULT_SCOPE)
112
        kwargs['params'] = {'decrypt': str(decrypt).lower()}
113
        kwargs['params']['scope'] = scope
114
        return self.get_resource_by_id(id=resource_name, **kwargs)
115
116
117
class KeyValuePairSetCommand(resource.ResourceCommand):
118
    display_attributes = ['name', 'value', 'expire_timestamp']
119
120
    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...
121
        super(KeyValuePairSetCommand, self).__init__(
122
            resource, 'set',
123
            'Set an existing %s.' % resource.get_display_name().lower(),
124
            *args, **kwargs
125
        )
126
127
        self.parser.add_argument('name',
128
                                 metavar='name',
129
                                 help='Name of the key value pair.')
130
        self.parser.add_argument('value', help='Value paired with the key.')
131
        self.parser.add_argument('-l', '--ttl', dest='ttl', type=int, default=None,
132
                                 help='TTL (in seconds) for this value.')
133
        self.parser.add_argument('-e', '--encrypt', dest='secret',
134
                                 action='store_true',
135
                                 help='Encrypt value before saving the value.')
136
        self.parser.add_argument('-s', '--scope', dest='scope', default=DEFAULT_SCOPE,
137
                                 help='Specify the scope under which you want ' +
138
                                      'to place the item.')
139
        self.parser.add_argument('-u', '--user', dest='user', default=None,
140
                                 help='User for user scoped items (admin only).')
141
142
    @add_auth_token_to_kwargs_from_cli
143
    def run(self, args, **kwargs):
144
        instance = KeyValuePair()
145
        instance.id = args.name  # TODO: refactor and get rid of id
146
        instance.name = args.name
147
        instance.value = args.value
148
        instance.scope = args.scope
149
        instance.user = args.user
150
151
        if args.secret:
152
            instance.secret = args.secret
153
154
        if args.ttl:
155
            instance.ttl = args.ttl
156
157
        return self.manager.update(instance, **kwargs)
158
159
    def run_and_print(self, args, **kwargs):
160
        instance = self.run(args, **kwargs)
161
        self.print_output(instance, table.PropertyValueTable,
162
                          attributes=self.display_attributes, json=args.json,
163
                          yaml=args.yaml)
164
165
166
class KeyValuePairDeleteCommand(resource.ResourceDeleteCommand):
167
    pk_argument_name = 'name'
168
169
    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...
170
        super(KeyValuePairDeleteCommand, self).__init__(resource, *args, **kwargs)
171
172
        self.parser.add_argument('-s', '--scope', dest='scope', default=DEFAULT_SCOPE,
173
                                 help='Specify the scope under which you want ' +
174
                                      'to place the item.')
175
        self.parser.add_argument('-u', '--user', dest='user', default=None,
176
                                 help='User for user scoped items (admin only).')
177
178
    @add_auth_token_to_kwargs_from_cli
179
    def run(self, args, **kwargs):
180
        resource_id = getattr(args, self.pk_argument_name, None)
181
        scope = getattr(args, 'scope', DEFAULT_SCOPE)
182
        kwargs['params'] = {}
183
        kwargs['params']['scope'] = scope
184
        instance = self.get_resource(resource_id, **kwargs)
185
186
        if not instance:
187
            raise resource.ResourceNotFoundError('KeyValuePair with id "%s" not found', resource_id)
188
189
        instance.id = resource_id  # TODO: refactor and get rid of id
190
        self.manager.delete(instance, **kwargs)
191
192
193
class KeyValuePairDeleteByPrefixCommand(resource.ResourceCommand):
194
    """
195
    Commands which delete all the key value pairs which match the provided
196
    prefix.
197
    """
198
    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...
199
        super(KeyValuePairDeleteByPrefixCommand, self).__init__(resource, 'delete_by_prefix',
200
            'Delete KeyValue pairs which match the provided prefix', *args, **kwargs)
201
202
        self.parser.add_argument('-p', '--prefix', required=True,
203
                                 help='Name prefix (e.g. twitter.TwitterSensor:)')
204
205
    @add_auth_token_to_kwargs_from_cli
206
    def run(self, args, **kwargs):
207
        prefix = args.prefix
208
        key_pairs = self.manager.get_all(prefix=prefix)
209
210
        to_delete = []
211
        for key_pair in key_pairs:
212
            key_pair.id = key_pair.name
213
            to_delete.append(key_pair)
214
215
        deleted = []
216
        for key_pair in to_delete:
217
            self.manager.delete(instance=key_pair, **kwargs)
218
            deleted.append(key_pair)
219
220
        return deleted
221
222
    def run_and_print(self, args, **kwargs):
223
        # TODO: Need to use args, instead of kwargs (args=) because of bad API
224
        # FIX ME
225
        deleted = self.run(args, **kwargs)
226
        key_ids = [key_pair.id for key_pair in deleted]
227
228
        print('Deleted %s keys' % (len(deleted)))
229
        print('Deleted key ids: %s' % (', '.join(key_ids)))
230
231
232
class KeyValuePairLoadCommand(resource.ResourceCommand):
233
    pk_argument_name = 'name'
234
    display_attributes = ['name', 'value']
235
236
    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...
237
        help_text = ('Load a list of %s from file.' %
238
                     resource.get_plural_display_name().lower())
239
        super(KeyValuePairLoadCommand, self).__init__(resource, 'load',
240
            help_text, *args, **kwargs)
241
242
        self.parser.add_argument(
243
            'file', help=('JSON file containing the %s to create.'
244
                          % resource.get_plural_display_name().lower()))
245
246
    @add_auth_token_to_kwargs_from_cli
247
    def run(self, args, **kwargs):
248
        file_path = os.path.normpath(pjoin(os.getcwd(), args.file))
249
250
        if not os.path.exists(args.file):
251
            raise ValueError('File "%s" doesn\'t exist' % (file_path))
252
253
        if not os.path.isfile(args.file):
254
            raise ValueError('"%s" is not a file' % (file_path))
255
256
        with open(file_path, 'r') as f:
257
            kvps = json.loads(f.read())
258
259
        instances = []
260
        for item in kvps:
261
            name = item['name']
262
            value = item['value']
263
264
            instance = KeyValuePair()
265
            instance.id = name  # TODO: refactor and get rid of id
266
            instance.name = name
267
            instance.value = value
268
269
            self.manager.update(instance, **kwargs)
270
            instances.append(instance)
271
        return instances
272
273
    def run_and_print(self, args, **kwargs):
274
        instances = self.run(args, **kwargs)
275
        self.print_output(instances, table.MultiColumnTable,
276
                          attributes=['id', 'name', 'value'], json=args.json, yaml=args.yaml)
277