Skip to content

Commit

Permalink
Use field masks from flask_restx marshal to do "partial object fetchi…
Browse files Browse the repository at this point in the history
…ng" using X-Fields header instead of custom query params, hopefully a bit more standard and more flexible

Example use curl -H "X-Fields: available_variables{interfaces},hostname" to only retreive hostname and variables regarding interfaces
  • Loading branch information
indy-independence committed Sep 20, 2023
1 parent b0fd8b2 commit fe3be7e
Showing 1 changed file with 16 additions and 16 deletions.
32 changes: 16 additions & 16 deletions src/cnaas_nms/api/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import List, Optional

from flask import make_response, request
from flask_restx import Namespace, Resource, fields
from flask_restx import Namespace, Resource, fields, marshal
from pydantic import ValidationError
from sqlalchemy import func
from sqlalchemy.exc import IntegrityError
Expand Down Expand Up @@ -171,6 +171,15 @@
},
)

device_generate_config_model = device_api.model(
"generate_config",
{
"hostname": fields.String,
"generated_config": fields.String,
"available_variables": fields.Raw,
},
)

stackmember_model = device_api.model(
"stackmember",
{
Expand Down Expand Up @@ -844,14 +853,11 @@ def post(self):
return resp


class DeviceConfigApi(Resource):
class DeviceGenerateConfigApi(Resource):
@jwt_required
@device_api.param("variables_only", "Only return available variables")
@device_api.param("interface_variables_only", "Only return available interface variables")
@device_api.param("config_only", "Only return full generated config")
@device_api.doc(model=device_generate_config_model)
def get(self, hostname: str):
"""Get device configuration"""
args = request.args
result = empty_result()
result["data"] = {"config": None}
if not Device.valid_hostname(hostname):
Expand All @@ -860,19 +866,13 @@ def get(self, hostname: str):
try:
config, template_vars = cnaas_nms.devicehandler.sync_devices.generate_only(hostname)
template_vars["host"] = hostname
result["data"]["config"] = {
data = {
"hostname": hostname,
"generated_config": config,
"available_variables": template_vars,
}
if "variables_only" in args and args["variables_only"]:
del result["data"]["config"]["generated_config"]
elif "interface_variables_only" in args and args["interface_variables_only"]:
del result["data"]["config"]["generated_config"]
interface_variables = result["data"]["config"]["available_variables"]["interfaces"]
result["data"]["config"]["available_variables"] = {"interfaces": interface_variables}
elif "config_only" in args and args["config_only"]:
del result["data"]["config"]["available_variables"]

result["data"]["config"] = marshal(data, device_generate_config_model, mask=request.headers.get("X-Fields"))

except Exception as e:
logger.exception(f"Exception while generating config for device {hostname}")
Expand Down Expand Up @@ -1207,7 +1207,7 @@ def post(self):
# Devices
device_api.add_resource(DeviceByIdApi, "/<int:device_id>")
device_api.add_resource(DeviceByHostnameApi, "/<string:hostname>")
device_api.add_resource(DeviceConfigApi, "/<string:hostname>/generate_config")
device_api.add_resource(DeviceGenerateConfigApi, "/<string:hostname>/generate_config")
device_api.add_resource(DeviceRunningConfigApi, "/<string:hostname>/running_config")
device_api.add_resource(DevicePreviousConfigApi, "/<string:hostname>/previous_config")
device_api.add_resource(DeviceApplyConfigApi, "/<string:hostname>/apply_config")
Expand Down

0 comments on commit fe3be7e

Please sign in to comment.