Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
brian-polling-manager
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
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
geant-swd
brian
brian-polling-manager
Commits
026bcfa2
Commit
026bcfa2
authored
1 year ago
by
Pelle Koster
Browse files
Options
Downloads
Patches
Plain Diff
validate router host to inventory provider when given
parent
ce714724
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
brian_polling_manager/interface_stats/cli.py
+29
-12
29 additions, 12 deletions
brian_polling_manager/interface_stats/cli.py
test/conftest.py
+124
-114
124 additions, 114 deletions
test/conftest.py
with
153 additions
and
126 deletions
brian_polling_manager/interface_stats/cli.py
+
29
−
12
View file @
026bcfa2
...
...
@@ -4,7 +4,7 @@ import os
import
pathlib
from
datetime
import
datetime
from
functools
import
partial
from
typing
import
Callable
,
Iterable
,
List
from
typing
import
Callable
,
Iterable
,
List
,
Sequence
,
Union
import
click
...
...
@@ -143,6 +143,22 @@ def get_routers_from_inventory_provider(vendor: Vendor, hosts: Iterable[str]):
return
[]
def
validate_hosts
(
router_fqdn
:
Sequence
[
str
],
vendor
:
Vendor
,
inprov_hosts
:
Union
[
str
,
Sequence
[
str
],
None
]
=
None
,
):
if
inprov_hosts
is
None
:
return
all_fqdns
=
get_routers_from_inventory_provider
(
vendor
,
inprov_hosts
)
extra_fqdns
=
set
(
router_fqdn
)
-
set
(
all_fqdns
)
if
extra_fqdns
:
raise
ValueError
(
f
"
Routers are not in inventory provider or not
{
vendor
.
value
}
:
"
f
"
{
'
'
.
join
(
extra_fqdns
)
}
"
)
def
main
(
app_config_params
:
dict
,
juniper_fqdns
:
List
[
str
],
...
...
@@ -153,27 +169,28 @@ def main(
):
if
not
juniper_fqdns
and
not
nokia_fqdns
:
inprov_hosts
=
app_config_params
.
get
(
"
inventory
"
,
[])
if
not
inprov_hosts
:
raise
ValueError
(
"
Must supply at least one inventory provider in config
"
)
juniper_fqdns
=
get_routers_from_inventory_provider
(
Vendor
.
JUNIPER
,
inprov_hosts
raise
click
.
ClickException
(
"
At least one --juniper or --nokia router is required
"
)
nokia_fqdns
=
get_routers_from_inventory_provider
(
Vendor
.
NOKIA
,
inprov_hosts
)
inprov_hosts
=
app_config_params
.
get
(
"
inventory
"
,
None
)
if
juniper_fqdns
:
juniper_ssh_params
=
app_config_params
.
get
(
"
juniper
"
)
validate_hosts
(
juniper_fqdns
,
vendor
=
Vendor
.
JUNIPER
,
inprov_hosts
=
inprov_hosts
)
juniper_ssh_params
=
app_config_params
.
get
(
Vendor
.
JUNIPER
.
value
)
if
not
juniper_ssh_params
:
raise
ValueError
(
"'
juniper
'
ssh params are required
"
)
raise
ValueError
(
f
"'
{
Vendor
.
JUNIPER
.
value
}
'
ssh params are required
"
)
juniper_netconf_provider
=
get_netconf_provider_
(
Vendor
.
JUNIPER
,
juniper_ssh_params
)
if
nokia_fqdns
:
nokia_ssh_params
=
app_config_params
.
get
(
"
nokia
"
)
validate_hosts
(
juniper_fqdns
,
vendor
=
Vendor
.
NOKIA
,
inprov_hosts
=
inprov_hosts
)
nokia_ssh_params
=
app_config_params
.
get
(
Vendor
.
NOKIA
.
value
)
if
not
nokia_ssh_params
:
raise
ValueError
(
"'
nokia
'
ssh params are required
"
)
raise
ValueError
(
f
"'
{
Vendor
.
JUNIPER
.
value
}
'
ssh params are required
"
)
nokia_netconf_provider
=
get_netconf_provider_
(
Vendor
.
NOKIA
,
nokia_ssh_params
)
...
...
@@ -227,7 +244,7 @@ def main(
"
nokia_fqdns
"
,
multiple
=
True
,
type
=
click
.
STRING
,
help
=
"
n
uniper
router fqdn(s)
"
,
help
=
"
n
okia
router fqdn(s)
"
,
callback
=
validate_hostname
,
)
@click.option
(
...
...
This diff is collapsed.
Click to expand it.
test/conftest.py
+
124
−
114
View file @
026bcfa2
...
...
@@ -3,16 +3,21 @@ import os
import
random
import
re
import
tempfile
from
unittest.mock
import
patch
import
brian_polling_manager.configuration
import
jsonschema
import
pytest
import
responses
@pytest.fixture
(
autouse
=
True
)
def
mocked_setup_logging
():
with
patch
.
object
(
brian_polling_manager
.
configuration
,
"
_setup_logging
"
)
as
mock
:
yield
mock
def
_load_test_data
(
filename
):
full_path
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'
data
'
,
filename
)
full_path
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"
data
"
,
filename
)
with
open
(
full_path
)
as
f
:
return
f
.
read
()
...
...
@@ -21,57 +26,53 @@ def _load_test_data(filename):
def
config
():
with
tempfile
.
TemporaryDirectory
()
as
state_dir_name
:
yield
{
'
inventory
'
:
[
'
http://bogus-inventory01.xxx.yyy:12345
'
,
'
http://bogus-inventory02.xxx.yyy:12345
'
,
'
http://bogus-inventory03.xxx.yyy:12345
'
"
inventory
"
:
[
"
http://bogus-inventory01.xxx.yyy:12345
"
,
"
http://bogus-inventory02.xxx.yyy:12345
"
,
"
http://bogus-inventory03.xxx.yyy:12345
"
,
],
'
sensu
'
:
{
'
api-base
'
:
[
'
https://bogus-sensu01.xxx.yyy:12345
'
,
'
https://bogus-sensu02.xxx.yyy:12345
'
,
'
https://bogus-sensu03.xxx.yyy:12345
'
"
sensu
"
:
{
"
api-base
"
:
[
"
https://bogus-sensu01.xxx.yyy:12345
"
,
"
https://bogus-sensu02.xxx.yyy:12345
"
,
"
https://bogus-sensu03.xxx.yyy:12345
"
,
],
'
api-key
'
:
'
abc-sensu-key-blah-blah
'
,
'
interface-check
'
:
{
'
script
'
:
'
/var/lib/sensu/bin/counter2influx.sh
'
,
'
measurement
'
:
'
counters
'
,
'
command
'
:
'
{script} {measurement}
'
'
{community} {hostname}
'
'
{interface} {ifIndex}
'
,
"
api-key
"
:
"
abc-sensu-key-blah-blah
"
,
"
interface-check
"
:
{
"
script
"
:
"
/var/lib/sensu/bin/counter2influx.sh
"
,
"
measurement
"
:
"
counters
"
,
"
command
"
:
"
{script} {measurement}
"
"
{community} {hostname}
"
"
{interface} {ifIndex}
"
,
},
"
gws-direct-interface-check
"
:
{
"
script
"
:
"
/var/lib/sensu/bin/poll-gws-direct.sh
"
,
"
measurement
"
:
"
gwsd_counters
"
,
"
command
"
:
"
{script} {measurement}
"
"
{nren} {isp} {hostname} {tag}
"
,
},
'
gws-direct-interface-check
'
:
{
'
script
'
:
'
/var/lib/sensu/bin/poll-gws-direct.sh
'
,
'
measurement
'
:
'
gwsd_counters
'
,
'
command
'
:
'
{script} {measurement}
'
'
{nren} {isp} {hostname} {tag}
'
"
dscp32-service-check
"
:
{
"
script
"
:
"
/var/lib/sensu/bin/poll-gws-indirect.sh
"
,
"
measurement
"
:
"
dscp32_counters
"
,
"
command
"
:
"
{script} {measurement} {service}
"
,
},
'
dscp32-service-check
'
:
{
'
script
'
:
'
/var/lib/sensu/bin/poll-gws-indirect.sh
'
,
'
measurement
'
:
'
dscp32_counters
'
,
'
command
'
:
'
{script} {measurement} {service}
'
"
eumetsat-multicast-check
"
:
{
"
script
"
:
"
/home/brian_checks/venv/eumetsat-multicast
"
,
"
measurement
"
:
"
multicast
"
,
"
command
"
:
"
{script}
"
"
--inventory http://localhost:18080
"
"
--measurement {measurement}
"
"
--hostname {hostname}
"
,
},
'
eumetsat-multicast-check
'
:
{
'
script
'
:
'
/home/brian_checks/venv/eumetsat-multicast
'
,
'
measurement
'
:
'
multicast
'
,
'
command
'
:
'
{script}
'
'
--inventory http://localhost:18080
'
'
--measurement {measurement}
'
'
--hostname {hostname}
'
}
},
'
statedir
'
:
state_dir_name
,
'
statsd
'
:
{
'
hostname
'
:
'
localhost
'
,
'
port
'
:
11119
,
'
prefix
'
:
'
zzzzz
'
}
"
statedir
"
:
state_dir_name
,
"
statsd
"
:
{
"
hostname
"
:
"
localhost
"
,
"
port
"
:
11119
,
"
prefix
"
:
"
zzzzz
"
},
}
@pytest.fixture
def
config_filename
(
config
):
with
tempfile
.
NamedTemporaryFile
(
mode
=
'
w
'
)
as
f
:
with
tempfile
.
NamedTemporaryFile
(
mode
=
"
w
"
)
as
f
:
f
.
write
(
json
.
dumps
(
config
))
f
.
flush
()
yield
f
.
name
...
...
@@ -81,114 +82,118 @@ def config_filename(config):
def
mocked_sensu
():
saved_sensu_checks
=
{
c
[
'
metadata
'
][
'
name
'
]:
c
for
c
in
json
.
loads
(
_load_test_data
(
'
checks.json
'
))
}
c
[
"
metadata
"
][
"
name
"
]:
c
for
c
in
json
.
loads
(
_load_test_data
(
"
checks.json
"
))
}
_check_schema
=
{
'
$schema
'
:
'
http://json-schema.org/draft-07/schema#
'
,
'
type
'
:
'
object
'
,
'
properties
'
:
{
'
command
'
:
{
'
type
'
:
'
string
'
},
'
interval
'
:
{
'
type
'
:
'
integer
'
},
'
subscriptions
'
:
{
'
type
'
:
'
array
'
,
'
items
'
:
{
'
type
'
:
'
string
'
}},
'
proxy_entity_name
'
:
{
'
type
'
:
'
string
'
},
'
round_robin
'
:
{
'
type
'
:
'
boolean
'
},
'
output_metric_format
'
:
{
'
enum
'
:
[
'
influxdb_line
'
]},
'
output_metric_handlers
'
:
{
'
type
'
:
'
array
'
,
'
items
'
:
{
'
type
'
:
'
string
'
}
},
'
metadata
'
:
{
'
type
'
:
'
object
'
,
'
properties
'
:
{
'
name
'
:
{
'
type
'
:
'
string
'
},
'
namespace
'
:
{
'
type
'
:
'
string
'
}
"
$schema
"
:
"
http://json-schema.org/draft-07/schema#
"
,
"
type
"
:
"
object
"
,
"
properties
"
:
{
"
command
"
:
{
"
type
"
:
"
string
"
},
"
interval
"
:
{
"
type
"
:
"
integer
"
},
"
subscriptions
"
:
{
"
type
"
:
"
array
"
,
"
items
"
:
{
"
type
"
:
"
string
"
}},
"
proxy_entity_name
"
:
{
"
type
"
:
"
string
"
},
"
round_robin
"
:
{
"
type
"
:
"
boolean
"
},
"
output_metric_format
"
:
{
"
enum
"
:
[
"
influxdb_line
"
]},
"
output_metric_handlers
"
:
{
"
type
"
:
"
array
"
,
"
items
"
:
{
"
type
"
:
"
string
"
}},
"
metadata
"
:
{
"
type
"
:
"
object
"
,
"
properties
"
:
{
"
name
"
:
{
"
type
"
:
"
string
"
},
"
namespace
"
:
{
"
type
"
:
"
string
"
},
},
'
required
'
:
[
'
name
'
,
'
namespace
'
],
'
additionalProperties
'
:
True
"
required
"
:
[
"
name
"
,
"
namespace
"
],
"
additionalProperties
"
:
True
,
},
},
'
required
'
:
[
'
command
'
,
'
interval
'
,
'
subscriptions
'
,
'
output_metric_format
'
,
'
output_metric_handlers
'
,
'
round_robin
'
,
'
metadata
'
],
'
additionalProperties
'
:
True
"
required
"
:
[
"
command
"
,
"
interval
"
,
"
subscriptions
"
,
"
output_metric_format
"
,
"
output_metric_handlers
"
,
"
round_robin
"
,
"
metadata
"
,
],
"
additionalProperties
"
:
True
,
}
# mocked api for returning all checks
responses
.
add
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks$
'
),
json
=
list
(
saved_sensu_checks
.
values
())
url
=
re
.
compile
(
r
"
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks$
"
),
json
=
list
(
saved_sensu_checks
.
values
())
,
)
def
new_check_callback
(
request
):
check
=
json
.
loads
(
request
.
body
)
jsonschema
.
validate
(
check
,
_check_schema
)
path_elems
=
request
.
path_url
.
split
(
'
/
'
)
path_elems
=
request
.
path_url
.
split
(
"
/
"
)
assert
len
(
path_elems
)
==
7
# sanity
assert
path_elems
[
5
]
==
check
[
'
metadata
'
][
'
namespace
'
]
assert
check
[
'
metadata
'
][
'
name
'
]
not
in
saved_sensu_checks
saved_sensu_checks
[
check
[
'
metadata
'
][
'
name
'
]]
=
check
return
(
201
,
{},
''
)
assert
path_elems
[
5
]
==
check
[
"
metadata
"
][
"
namespace
"
]
assert
check
[
"
metadata
"
][
"
name
"
]
not
in
saved_sensu_checks
saved_sensu_checks
[
check
[
"
metadata
"
][
"
name
"
]]
=
check
return
(
201
,
{},
""
)
# mocked api for creating a check
responses
.
add_callback
(
method
=
responses
.
POST
,
url
=
re
.
compile
(
r
'
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks$
'
),
callback
=
new_check_callback
)
url
=
re
.
compile
(
r
"
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks$
"
),
callback
=
new_check_callback
,
)
def
update_check_callback
(
request
):
check
=
json
.
loads
(
request
.
body
)
jsonschema
.
validate
(
check
,
_check_schema
)
path_elems
=
request
.
path_url
.
split
(
'
/
'
)
path_elems
=
request
.
path_url
.
split
(
"
/
"
)
assert
len
(
path_elems
)
==
8
# sanity
assert
path_elems
[
5
]
==
check
[
'
metadata
'
][
'
namespace
'
]
assert
path_elems
[
-
1
]
==
check
[
'
metadata
'
][
'
name
'
]
assert
check
[
'
metadata
'
][
'
name
'
]
in
saved_sensu_checks
,
\
'
we only intend to call this method for updating existing checks
'
saved_sensu_checks
[
check
[
'
metadata
'
][
'
name
'
]]
=
check
return
201
,
{},
''
assert
path_elems
[
5
]
==
check
[
"
metadata
"
][
"
namespace
"
]
assert
path_elems
[
-
1
]
==
check
[
"
metadata
"
][
"
name
"
]
assert
(
check
[
"
metadata
"
][
"
name
"
]
in
saved_sensu_checks
),
"
we only intend to call this method for updating existing checks
"
saved_sensu_checks
[
check
[
"
metadata
"
][
"
name
"
]]
=
check
return
201
,
{},
""
# mocked api for updating a check
responses
.
add_callback
(
method
=
responses
.
PUT
,
url
=
re
.
compile
(
r
'
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks/[^\/]+$
'
)
,
callback
=
update_check_callback
)
url
=
re
.
compile
(
r
"
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks/[^\/]+$
"
),
callback
=
update_check_callback
,
)
def
delete_check_callback
(
request
):
path_elems
=
request
.
path_url
.
split
(
'
/
'
)
path_elems
=
request
.
path_url
.
split
(
"
/
"
)
assert
len
(
path_elems
)
==
8
# sanity
del
saved_sensu_checks
[
path_elems
[
-
1
]]
return
204
,
{},
''
return
204
,
{},
""
# mocked api for deleting a check
responses
.
add_callback
(
method
=
responses
.
DELETE
,
url
=
re
.
compile
(
r
'
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks/[^\/]+$
'
)
,
callback
=
delete_check_callback
)
url
=
re
.
compile
(
r
"
.*sensu.+/api/core/v2/namespaces/[^\/]+/checks/[^\/]+$
"
),
callback
=
delete_check_callback
,
)
def
get_events_callback
(
request
):
return
200
,
{},
_load_test_data
(
'
events.json
'
)
return
200
,
{},
_load_test_data
(
"
events.json
"
)
# mocked api for returning all events
responses
.
add_callback
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*sensu.+/api/core/v2/namespaces/[^\/]+/events$
'
),
callback
=
get_events_callback
)
url
=
re
.
compile
(
r
"
.*sensu.+/api/core/v2/namespaces/[^\/]+/events$
"
),
callback
=
get_events_callback
,
)
def
delete_event_callback
(
request
):
return
204
,
{},
''
return
204
,
{},
""
# mocked api for deleting an event
responses
.
add_callback
(
method
=
responses
.
DELETE
,
url
=
re
.
compile
(
r
'
.*sensu.+/api/core/v2/namespaces/default/events/.*$
'
)
,
callback
=
delete_event_callback
)
url
=
re
.
compile
(
r
"
.*sensu.+/api/core/v2/namespaces/default/events/.*$
"
),
callback
=
delete_event_callback
,
)
yield
saved_sensu_checks
...
...
@@ -198,27 +203,32 @@ def mocked_inventory():
responses
.
add
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*inventory.+/poller/interfaces.*
'
),
body
=
_load_test_data
(
'
interfaces.json
'
))
url
=
re
.
compile
(
r
"
.*inventory.+/poller/interfaces.*
"
),
body
=
_load_test_data
(
"
interfaces.json
"
),
)
responses
.
add
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*inventory.+/poller/gws/direct
'
),
body
=
_load_test_data
(
'
gws-direct.json
'
))
url
=
re
.
compile
(
r
"
.*inventory.+/poller/gws/direct
"
),
body
=
_load_test_data
(
"
gws-direct.json
"
),
)
responses
.
add
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*inventory.+/poller/gws/indirect.*
'
),
body
=
_load_test_data
(
'
gws-indirect.json
'
))
url
=
re
.
compile
(
r
"
.*inventory.+/poller/gws/indirect.*
"
),
body
=
_load_test_data
(
"
gws-indirect.json
"
),
)
responses
.
add
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*inventory.+/poller/eumetsat-multicast
'
),
body
=
_load_test_data
(
'
eumetsat-multicast.json
'
))
url
=
re
.
compile
(
r
"
.*inventory.+/poller/eumetsat-multicast
"
),
body
=
_load_test_data
(
"
eumetsat-multicast.json
"
),
)
bogus_version
=
{
'
latch
'
:
{
'
timestamp
'
:
10000
*
random
.
random
()}}
bogus_version
=
{
"
latch
"
:
{
"
timestamp
"
:
10000
*
random
.
random
()}}
# mocked api for returning all checks
responses
.
add
(
method
=
responses
.
GET
,
url
=
re
.
compile
(
r
'
.*inventory.+/version.*
'
),
body
=
json
.
dumps
(
bogus_version
))
url
=
re
.
compile
(
r
"
.*inventory.+/version.*
"
),
body
=
json
.
dumps
(
bogus_version
),
)
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