Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
Warden - archive
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
713
Warden
Warden - archive
Commits
683d586a
Commit
683d586a
authored
Mar 8, 2023
by
Jakub Maloštík
Browse files
Options
Downloads
Patches
Plain Diff
Use ErrorMessage class for errors instead of dicts
parent
e18f658d
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
warden_server/warden_server.py
+150
-101
150 additions, 101 deletions
warden_server/warden_server.py
with
150 additions
and
101 deletions
warden_server/warden_server.py
+
150
−
101
View file @
683d586a
...
@@ -51,94 +51,134 @@ class Encoder(json.JSONEncoder):
...
@@ -51,94 +51,134 @@ class Encoder(json.JSONEncoder):
def
default
(
self
,
o
):
def
default
(
self
,
o
):
if
isinstance
(
o
,
Error
):
if
isinstance
(
o
,
Error
):
return
o
.
to_dict
()
return
o
.
to_dict
()
if
isinstance
(
o
,
ErrorMessage
):
out
=
o
.
other_args
.
copy
()
out
.
pop
(
"
exc
"
,
None
)
out
[
"
error
"
]
=
o
.
error
out
[
"
message
"
]
=
o
.
message
if
o
.
events
:
out
[
"
events
"
]
=
list
(
o
.
events
)
return
out
return
str
(
o
)
return
str
(
o
)
class
ErrorMessage
(
Exception
):
def
__init__
(
self
,
error
,
message
,
events
=
None
,
unique_id
=
None
,
**
kwargs
):
super
(
Exception
,
self
).
__setattr__
(
"
error
"
,
error
)
super
(
Exception
,
self
).
__setattr__
(
"
message
"
,
message
)
super
(
Exception
,
self
).
__setattr__
(
"
unique_id
"
,
unique_id
)
self
.
events
=
set
()
if
events
is
None
else
set
(
events
)
self
.
other_args
=
kwargs
def
__repr__
(
self
):
return
"
%s(error=%d, message=%s)
"
%
(
type
(
self
).
__name__
,
self
.
error
,
repr
(
self
.
message
)
)
def
__str__
(
self
):
if
sys
.
version_info
[
0
]
<
3
:
return
self
.
str_err
().
encode
(
'
ascii
'
,
'
backslashereplace
'
)
return
self
.
str_err
()
def
str_err
(
self
):
exc
=
self
.
other_args
.
get
(
"
exc
"
,
None
)
if
exc
in
(
None
,
(
None
,
None
,
None
)):
exc_cause
=
""
else
:
exc_cause
=
"
(cause was %s: %s)
"
%
(
exc
[
0
].
__name__
,
str
(
exc
[
1
]))
return
"
Error(%s) %s%s
"
%
(
self
.
error
,
self
.
message
,
exc_cause
)
def
str_info
(
self
):
arg_copy
=
self
.
other_args
.
copy
()
arg_copy
.
pop
(
"
req_id
"
,
None
)
arg_copy
.
pop
(
"
method
"
,
None
)
arg_copy
.
pop
(
"
exc
"
,
None
)
if
arg_copy
:
return
"
Detail: %s
"
%
json
.
dumps
(
arg_copy
,
cls
=
Encoder
)
return
""
def
str_debug
(
self
):
exc
=
self
.
other_args
.
get
(
"
exc
"
,
None
)
if
exc
in
(
None
,
(
None
,
None
,
None
)):
return
""
exc_tb
=
exc
[
2
]
if
not
exc_tb
:
return
""
return
"
Traceback:
\n
"
+
""
.
join
(
format_tb
(
exc_tb
))
def
__getattr__
(
self
,
name
):
if
name
in
self
.
other_args
:
return
self
.
other_args
[
name
]
raise
AttributeError
def
__setattr__
(
self
,
name
,
value
):
if
name
in
(
"
events
"
,
"
exc
"
,
"
other_args
"
):
super
(
Exception
,
self
).
__setattr__
(
name
,
value
)
return
if
name
in
(
"
error
"
,
"
message
"
,
"
unique_id
"
):
raise
AttributeError
(
"
Cannot change the attribute %s
"
%
name
)
self
.
other_args
[
name
]
=
value
class
Error
(
Exception
):
class
Error
(
Exception
):
def
__init__
(
self
,
method
=
None
,
req_id
=
None
,
errors
=
None
,
**
kwargs
):
def
__init__
(
self
,
method
=
None
,
req_id
=
None
,
errors
=
None
,
**
kwargs
):
self
.
method
=
method
self
.
method
=
method
self
.
req_id
=
req_id
self
.
req_id
=
req_id
self
.
errors
=
[
kwargs
]
if
kwargs
else
[]
if
"
message
"
in
kwargs
:
kwargs
.
setdefault
(
"
error
"
,
500
)
self
.
errors
=
[
ErrorMessage
(
**
kwargs
)]
else
:
self
.
errors
=
[]
if
errors
:
if
errors
:
self
.
errors
.
extend
(
errors
)
self
.
errors
.
extend
(
errors
)
def
append
(
self
,
_events
=
None
,
**
kwargs
):
def
append
(
self
,
_events
=
None
,
**
kwargs
):
self
.
errors
.
append
(
kwargs
)
kwargs
.
setdefault
(
"
message
"
,
"
No further information
"
)
kwargs
.
setdefault
(
"
error
"
,
500
)
self
.
errors
.
append
(
ErrorMessage
(
**
kwargs
))
def
get_http_err_msg
(
self
):
def
get_http_err_msg
(
self
):
try
:
try
:
err
=
self
.
errors
[
0
]
[
"
error
"
]
err
=
self
.
errors
[
0
]
.
error
msg
=
self
.
errors
[
0
]
[
"
message
"
].
replace
(
"
\n
"
,
"
"
)
msg
=
self
.
errors
[
0
]
.
message
except
(
IndexError
,
Key
Error
):
except
(
IndexError
,
Attribute
Error
):
err
=
500
err
=
500
msg
=
"
There
'
s NO self-destruction button! Ah, you
'
ve just found it...
"
msg
=
"
There
'
s NO self-destruction button! Ah, you
'
ve just found it...
"
for
e
in
self
.
errors
:
return
err
,
msg
next_err
=
e
.
get
(
"
error
"
,
500
)
if
err
!=
next_err
:
if
not
all
(
msg
==
e
.
message
for
e
in
self
.
errors
):
# messages not the same, get Multiple errors
msg
=
"
Multiple errors
"
if
not
all
(
err
==
e
.
error
for
e
in
self
.
errors
):
# errors not same, round to basic err code (400, 500)
# errors not same, round to basic err code (400, 500)
# and use the highest one
# and use the highest one
err
=
max
(
err
//
100
,
next_err
//
100
)
*
100
err
=
max
(
e
.
error
for
e
in
self
.
errors
)
//
100
*
100
next_msg
=
e
.
get
(
"
message
"
,
"
Unknown error
"
).
replace
(
"
\n
"
,
"
"
)
if
msg
!=
next_msg
:
msg
=
"
Multiple errors
"
msg
=
""
.
join
((
c
if
'
\x20
'
<=
c
!=
'
\x7f
'
else
r
'
\x{:02x}
'
.
format
(
ord
(
c
)))
for
c
in
msg
)
# escape control characters
msg
=
""
.
join
((
c
if
'
\x20
'
<=
c
!=
'
\x7f
'
else
r
'
\x{:02x}
'
.
format
(
ord
(
c
)))
for
c
in
msg
)
# escape control characters
return
err
,
msg
return
err
,
msg
def
__str__
(
self
):
def
__str__
(
self
):
return
"
\n
"
.
join
(
s
elf
.
str_er
r
(
e
)
for
e
in
self
.
errors
)
return
"
\n
"
.
join
(
s
t
r
(
e
)
for
e
in
self
.
errors
)
def
log
(
self
,
logger
,
prio
=
logging
.
ERROR
):
def
log
(
self
,
logger
,
prio
=
logging
.
ERROR
):
for
e
in
self
.
errors
:
for
e
in
self
.
errors
:
logger
.
log
(
prio
,
self
.
str_err
(
e
))
logger
.
log
(
prio
,
e
.
str_err
())
info
=
self
.
str_info
(
e
)
info
=
e
.
str_info
()
if
info
:
if
info
:
logger
.
info
(
info
)
logger
.
info
(
info
)
debug
=
self
.
str_debug
(
e
)
debug
=
e
.
str_debug
()
if
debug
:
if
debug
:
logger
.
debug
(
debug
)
logger
.
debug
(
debug
)
def
str_err
(
self
,
e
):
out
=
[]
out
.
append
(
"
Error(%s) %s
"
%
(
e
.
get
(
"
error
"
,
0
),
e
.
get
(
"
message
"
,
"
Unknown error
"
)))
if
"
exc
"
in
e
and
e
[
"
exc
"
]:
out
.
append
(
"
(cause was %s: %s)
"
%
(
e
[
"
exc
"
][
0
].
__name__
,
str
(
e
[
"
exc
"
][
1
])))
return
""
.
join
(
out
)
def
str_info
(
self
,
e
):
ecopy
=
dict
(
e
)
# shallow copy
ecopy
.
pop
(
"
req_id
"
,
None
)
ecopy
.
pop
(
"
method
"
,
None
)
ecopy
.
pop
(
"
error
"
,
None
)
ecopy
.
pop
(
"
message
"
,
None
)
ecopy
.
pop
(
"
exc
"
,
None
)
if
ecopy
:
out
=
"
Detail: %s
"
%
(
json
.
dumps
(
ecopy
,
cls
=
Encoder
))
else
:
out
=
""
return
out
def
str_debug
(
self
,
e
):
out
=
[]
if
not
e
.
get
(
"
exc
"
):
return
""
exc_tb
=
e
[
"
exc
"
][
2
]
if
exc_tb
:
out
.
append
(
"
Traceback:
\n
"
)
out
.
extend
(
format_tb
(
exc_tb
))
return
""
.
join
(
out
)
def
to_dict
(
self
):
def
to_dict
(
self
):
errlist
=
[]
for
e
in
self
.
errors
:
ecopy
=
dict
(
e
)
ecopy
.
pop
(
"
exc
"
,
None
)
errlist
.
append
(
ecopy
)
d
=
{
d
=
{
"
method
"
:
self
.
method
,
"
method
"
:
self
.
method
,
"
req_id
"
:
self
.
req_id
,
"
req_id
"
:
self
.
req_id
,
"
errors
"
:
errlist
"
errors
"
:
self
.
errors
}
}
return
d
return
d
...
@@ -466,14 +506,15 @@ class JSONSchemaValidator(NoValidator):
...
@@ -466,14 +506,15 @@ class JSONSchemaValidator(NoValidator):
res
=
[]
res
=
[]
for
error
in
sorted
(
self
.
validator
.
iter_errors
(
event
),
key
=
sortkey
):
for
error
in
sorted
(
self
.
validator
.
iter_errors
(
event
),
key
=
sortkey
):
res
.
append
(
{
res
.
append
(
"
e
rror
"
:
460
,
E
rror
Message
(
"
message
"
:
"
Validation error: key
\"
%s
\"
, value
\"
%s
\"
"
%
(
460
,
"
Validation error: key
\"
%s
\"
, value
\"
%s
\"
"
%
(
"
/
"
.
join
(
str
(
v
)
for
v
in
error
.
path
),
"
/
"
.
join
(
map
(
str
,
error
.
path
)
)
,
error
.
instance
error
.
instance
),
),
"
expected
"
:
error
.
schema
.
get
(
'
description
'
,
'
no additional info
'
)
expected
=
error
.
schema
.
get
(
'
description
'
,
'
no additional info
'
)
})
)
)
return
res
return
res
...
@@ -806,7 +847,7 @@ class DataBase(ObjectBase):
...
@@ -806,7 +847,7 @@ class DataBase(ObjectBase):
except
Exception
as
e
:
except
Exception
as
e
:
exception
=
self
.
req
.
error
(
message
=
"
DB error
"
,
error
=
500
,
exc
=
sys
.
exc_info
(),
env
=
self
.
req
.
env
)
exception
=
self
.
req
.
error
(
message
=
"
DB error
"
,
error
=
500
,
exc
=
sys
.
exc_info
(),
env
=
self
.
req
.
env
)
exception
.
log
(
self
.
log
)
exception
.
log
(
self
.
log
)
return
[
{
"
e
rror
"
:
500
,
"
m
essage
"
:
"
DB error %s
"
%
type
(
e
).
__name__
}
]
return
[
E
rror
M
essage
(
500
,
"
DB error %s
"
%
type
(
e
).
__name__
)
]
@abc.abstractmethod
@abc.abstractmethod
def
_build_insert_last_received_id
(
self
,
client
,
id
):
def
_build_insert_last_received_id
(
self
,
client
,
id
):
...
@@ -1688,28 +1729,23 @@ class WardenHandler(ObjectBase):
...
@@ -1688,28 +1729,23 @@ class WardenHandler(ObjectBase):
return
res
return
res
def
check_node
(
self
,
event
,
name
):
def
check_node
(
self
,
event
,
event_indx
,
name
):
try
:
try
:
ev_id
=
event
[
'
Node
'
][
0
][
'
Name
'
].
lower
()
ev_id
=
event
[
'
Node
'
][
0
][
'
Name
'
].
lower
()
except
(
KeyError
,
TypeError
,
IndexError
):
except
(
KeyError
,
TypeError
,
IndexError
):
# Event does not bear valid Node attribute
# Event does not bear valid Node attribute
return
[{
"
error
"
:
422
,
"
message
"
:
"
Event does not bear valid Node attribute
"
}]
return
[
ErrorMessage
(
422
,
"
Event does not bear valid Node attribute
"
,
{
event_indx
})
]
if
ev_id
!=
name
:
if
ev_id
!=
name
:
return
[{
"
error
"
:
422
,
"
message
"
:
"
Node does not correspond with saving client
"
}]
return
[
ErrorMessage
(
422
,
"
Node does not correspond with saving client
"
,
{
event_indx
})
]
return
[]
return
[]
def
add_event_nums
(
self
,
ilist
,
events
,
errlist
):
def
add_errors
(
self
,
errs_to_add
):
for
err
in
errlist
:
for
err
in
errs_to_add
:
err
.
setdefault
(
"
events
"
,
[]).
extend
(
ilist
)
self
.
errs
.
setdefault
((
err
.
error
,
err
.
message
,
err
.
unique_id
),
err
).
events
.
update
(
err
.
events
)
ev_ids
=
err
.
setdefault
(
"
events_id
"
,
[])
for
i
in
ilist
:
event
=
events
[
i
]
try
:
id
=
event
[
"
ID
"
]
except
(
KeyError
,
TypeError
,
ValueError
):
id
=
None
ev_ids
.
append
(
id
)
return
errlist
@expose
(
write
=
True
)
@expose
(
write
=
True
)
@json_wrapper
@json_wrapper
...
@@ -1717,40 +1753,55 @@ class WardenHandler(ObjectBase):
...
@@ -1717,40 +1753,55 @@ class WardenHandler(ObjectBase):
if
not
isinstance
(
events
,
list
):
if
not
isinstance
(
events
,
list
):
raise
self
.
req
.
error
(
message
=
"
List of events expected.
"
,
error
=
400
)
raise
self
.
req
.
error
(
message
=
"
List of events expected.
"
,
error
=
400
)
errs
=
[]
self
.
errs
=
{}
if
len
(
events
)
>
self
.
send_events_limit
:
if
len
(
events
)
>
self
.
send_events_limit
:
errs
.
extend
(
self
.
add_event_nums
(
range
(
self
.
send_events_limit
,
len
(
events
)),
events
,
[
self
.
add_errors
(
{
"
error
"
:
507
,
"
message
"
:
"
Too much events in one batch.
"
,
"
send_events_limit
"
:
self
.
send_events_limit
}]))
[
ErrorMessage
(
507
,
"
Too many events in one batch.
"
,
set
(
range
(
self
.
send_events_limit
,
len
(
events
))),
send_events_limit
=
self
.
send_events_limit
)
]
)
saved
=
0
events_tosend
=
[]
events_tosend
=
[]
events_raw
=
[]
events_raw
=
[]
events_nums
=
[]
events_nums
=
[]
for
i
,
event
in
enumerate
(
events
[
0
:
self
.
send_events_limit
]):
for
i
,
event
in
enumerate
(
events
[
0
:
self
.
send_events_limit
]):
v_errs
=
self
.
validator
.
check
(
event
)
v_errs
=
self
.
validator
.
check
(
event
)
if
v_errs
:
if
v_errs
:
errs
.
extend
(
self
.
add_event_nums
([
i
],
events
,
v_errs
)
)
self
.
add_errors
(
v_errs
)
continue
continue
node_errs
=
self
.
check_node
(
event
,
self
.
req
.
client
.
name
)
node_errs
=
self
.
check_node
(
event
,
i
,
self
.
req
.
client
.
name
)
if
node_errs
:
if
node_errs
:
errs
.
extend
(
self
.
add_event_nums
([
i
],
events
,
node_errs
)
)
self
.
add_errors
(
node_errs
)
continue
continue
if
self
.
req
.
client
.
test
and
'
Test
'
not
in
event
.
get
(
'
Category
'
,
[]):
if
self
.
req
.
client
.
test
and
'
Test
'
not
in
event
.
get
(
'
Category
'
,
[]):
errs
.
extend
(
self
.
add_errors
(
self
.
add_event_nums
([
i
],
events
,
[{
[
"
error
"
:
422
,
ErrorMessage
(
"
message
"
:
"
You
'
re allowed to send only messages, containing
\"
Test
\"
among categories.
"
,
422
,
"
You
'
re allowed to send only messages containing
\"
Test
\"
among categories.
"
,
{
i
},
"
categories
"
:
event
.
get
(
'
Category
'
,
[])}]))
# Ensure that 1the error message is contained for every combination of categories
unique_id
=
tuple
(
event
.
get
(
'
Category
'
,
[])),
categories
=
event
.
get
(
'
Category
'
,
[])
)
]
)
continue
continue
raw_event
=
json
.
dumps
(
event
)
raw_event
=
json
.
dumps
(
event
)
if
len
(
raw_event
)
>=
self
.
db
.
event_size_limit
:
if
len
(
raw_event
)
>=
self
.
db
.
event_size_limit
:
errs
.
extend
(
self
.
add_errors
(
self
.
add_event_nums
([
i
],
events
,
[
[
{
"
error
"
:
413
,
"
message
"
:
"
Event too long (>%i B)
"
%
self
.
db
.
event_size_limit
}
ErrorMessage
(
]))
413
,
"
Event too long (>%i B)
"
%
self
.
db
.
event_size_limit
,
{
i
},
event_size_limit
=
self
.
db
.
event_size_limit
)
]
)
continue
continue
events_tosend
.
append
(
event
)
events_tosend
.
append
(
event
)
...
@@ -1758,15 +1809,13 @@ class WardenHandler(ObjectBase):
...
@@ -1758,15 +1809,13 @@ class WardenHandler(ObjectBase):
events_nums
.
append
(
i
)
events_nums
.
append
(
i
)
db_errs
=
self
.
db
.
store_events
(
self
.
req
.
client
,
events_tosend
,
events_raw
)
db_errs
=
self
.
db
.
store_events
(
self
.
req
.
client
,
events_tosend
,
events_raw
)
if
db_errs
:
self
.
add_errors
(
db_errs
)
errs
.
extend
(
self
.
add_event_nums
(
events_nums
,
events_tosend
,
db_errs
))
saved
=
0
saved
=
0
if
db_errs
else
len
(
events_tosend
)
else
:
saved
=
len
(
events_tosend
)
self
.
log
.
info
(
"
Saved %i events
"
%
saved
)
self
.
log
.
info
(
"
Saved %i events
"
%
saved
)
if
errs
:
if
self
.
errs
:
raise
self
.
req
.
error
(
errors
=
errs
)
raise
self
.
req
.
error
(
errors
=
self
.
errs
.
values
()
)
return
{
"
saved
"
:
saved
}
return
{
"
saved
"
:
saved
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment