-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrmobj
executable file
·203 lines (170 loc) · 7.22 KB
/
rmobj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#!/usr/bin/env python
import boto.s3
import sys
import logging
from umobj.compat import PYTHON2
from umobj.bucket import delete_bucket
from umobj.key import delete_key, is_directory
from umobj.utils import umobj_logging, umobj_init, \
umobj_get_bucket_key_pair_from_string
from umobj.obj import Obj
from umobj.options import umobj_parser, get_logging_level
if PYTHON2:
input = raw_input # noqa
def ask_yes_no(question):
"""Ask a yes or no question and return True if yes."""
ans = input('%s [yes/no] ' % question).lower()
return ans == 'yes' or ans == 'y'
def no_to_question(question):
"""Return True if the answer to the yes/no question is no."""
return not ask_yes_no(question)
if __name__ == "__main__":
umobj_init()
description = 'Remove Bucket(s) and Object(s)'
parser = umobj_parser(description=description)
parser.add_recursive()
parser.add_force()
parser.add_interactive()
parser.add_s3path(number='+', help='BUCKET:KEY', name='S3PATH')
args = parser.parse_args()
umobj_logging(get_logging_level(args)) # set up logging
logging.info("Running %s" % sys.argv)
recursive = args.recursive
interactive = args.interactive
force = args.force
_exit_status = [0]
_file_existence_error = [False]
def set_exit_status(status):
_exit_status[0] = status
def exit_status():
return _exit_status[0]
def flag_file_existence_error():
_file_existence_error[0] = True
def file_existence_error():
return _file_existence_error[0]
def delete_key_with_status(bucket, key_name, check_exists=False):
status = delete_key(bucket, key_name, check_exists=check_exists)
if status is False:
logging.error("rmobj: cannot remove '%s:%s': No such key" %
(bucket.name, key_name))
flag_file_existence_error()
prompt_once = False
if recursive:
prompt_once = True
if interactive:
prompt_once = False
# note that force is last since it is King arbiter of whether or not
# we can be interactive.
if force:
interactive = False
prompt_once = False
if not Obj.connect(host=args.host,
port=args.port,
access_key=args.access_key,
secret_key=args.secret_key):
logging.error('Unable to contact object store.')
sys.exit(1)
if prompt_once and recursive:
if len(args.S3PATH) == 1:
question = 'Remove 1 argument recursively?'
else:
question = 'Remove %s arguments recursively?' % len(args.S3PATH)
if no_to_question(question):
sys.exit(0)
for arg in args.S3PATH:
bucket_name, key_name = umobj_get_bucket_key_pair_from_string(arg)
delete_bucket_contents = False
want_delete_bucket = False
if key_name is None or key_name == '*':
delete_bucket_contents = True
if key_name is None:
want_delete_bucket = True
try:
bucket = Obj.conn.get_bucket(bucket_name)
except boto.exception.S3ResponseError as e:
if e.status == 404:
logging.error("Bucket %s does not exist." % bucket_name)
flag_file_existence_error()
else:
logging.error("Insufficient permissions.")
continue
logging.info("Working on bucket %s" % bucket_name)
if recursive:
# removing all content inside bucket
if delete_bucket_contents:
if interactive:
question = " Are you sure you want to remove all the ' + \
'contents of the bucket '%s'?" % bucket.name
if no_to_question(question):
logging.info("Skipping recursive deletion of " +
"bucket %s contents" % bucket_name)
continue
for key in bucket.list():
delete_key_with_status(bucket, key.name)
# removing the bucket itself
if want_delete_bucket:
if interactive:
question = (" Do you want to remove the"
" bucket '%s'?" % bucket.name)
if no_to_question(question):
logging.info("Not deleting bucket %s"
% bucket_name)
continue
delete_bucket(Obj.conn, bucket.name)
logging.info("Deleting the bucket %s" % bucket_name)
# if we deleted all the keys and/or the bucket, then there's
# nothing left to do for individual keys below, so continue.
continue
# removing a directory or file
if is_directory(bucket, key_name):
# ensure trailing slash
if not key_name.endswith('/'):
key_name = key_name + '/'
was_something_to_list = False
for key in bucket.list(prefix=key_name):
was_something_to_list = True
if interactive and no_to_question("rmobj: delete '%s'?"
% key.name):
continue
delete_key_with_status(bucket, key.name)
if not was_something_to_list and not force:
logging.error("rmobj: cannot remove '%s': No such key"
% arg)
flag_file_existence_error()
else: # individal file
if interactive and no_to_question("rmobj: delete '%s'?"
% key_name):
continue
delete_key_with_status(bucket, key_name, check_exists=True)
else: # non-recursive
if want_delete_bucket:
logging.error('Cannot delete bucket %s, ' % bucket.name +
'please use the recursive option.')
set_exit_status(1)
continue
elif delete_bucket_contents:
logging.error("rmobj: cannot delete all content from "
"bucket %s. " % bucket.name +
"Please use the recursive option.")
set_exit_status(1)
continue
elif is_directory(bucket, key_name):
logging.error("rmobj: cannot remove '%s': Is a directory"
% arg)
set_exit_status(1)
continue
logging.info('Deleting %s...' % arg)
delete_key_with_status(bucket, key_name, check_exists=True)
# this can be a little confusing... If someone used the API wrong, we
# will ALWAYS exit non-zero regardless of if the force flag was present.
# Otherwise, we exit non-zero if there were file existence errors unless
# the force flag was given.
if exit_status() != 0:
sys.exit(exit_status())
elif force:
sys.exit(0)
else:
if file_existence_error():
sys.exit(1)
else:
sys.exit(0)