Skip to content

Commit bd6c4f4

Browse files
Added APIFirewallTrafficShaperQueueDelete model to delete existing queues, updated unit test to test queue deletions
1 parent 39c4e13 commit bd6c4f4

4 files changed

Lines changed: 161 additions & 5 deletions

File tree

pfSense-pkg-API/files/etc/inc/api/endpoints/APIFirewallTrafficShaperQueue.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ class APIFirewallTrafficShaperQueue extends APIEndpoint {
2323
protected function post() {
2424
return (new APIFirewallTrafficShaperQueueCreate())->call();
2525
}
26+
27+
protected function delete() {
28+
return (new APIFirewallTrafficShaperQueueDelete())->call();
29+
}
2630
}

pfSense-pkg-API/files/etc/inc/api/framework/APIResponse.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,12 @@ function get($id, $data=[], $all=false) {
18501850
"return" => $id,
18511851
"message" => "Firewall traffic shaper queue realtime3 value must be a bandwidth formatted string"
18521852
],
1853+
4145 => [
1854+
"status" => "bad request",
1855+
"code" => 400,
1856+
"return" => $id,
1857+
"message" => "Firewall traffic shaper queue name does not exist"
1858+
],
18531859

18541860
//5000-5999 reserved for /users API calls
18551861
5000 => [
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
// Copyright 2021 Jared Hendrickson
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// 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+
require_once("api/framework/APIModel.inc");
17+
require_once("api/framework/APIResponse.inc");
18+
19+
class APIFirewallTrafficShaperQueueDelete extends APIModel {
20+
public $parent_id;
21+
22+
# Create our method constructor
23+
public function __construct() {
24+
parent::__construct();
25+
$this->privileges = ["page-all", "page-firewall-trafficshaper-queues"];
26+
$this->change_note = "Deleted firewall traffic shaper queue via API";
27+
}
28+
29+
public function action() {
30+
unset($this->config["shaper"]["queue"][$this->parent_id]["queue"][$this->id]);
31+
$this->write_config();
32+
mark_subsystem_dirty('shaper');
33+
34+
# Only reload the filter immediately if it was requested by the client
35+
if ($this->initial_data["apply"] === true) {
36+
# Reload the filter, reset RRD logs and mark the subsystem as applied
37+
filter_configure();
38+
system("rm -f /var/db/rrd/*queuedrops.rrd");
39+
system("rm -f /var/db/rrd/*queues.rrd");
40+
enable_rrd_graphing();
41+
clear_subsystem_dirty('shaper');
42+
}
43+
return APIResponse\get(0, $this->validated_data);
44+
}
45+
46+
public function validate_payload() {
47+
$this->__validate_interface();
48+
$this->__validate_name();
49+
}
50+
51+
private function __validate_interface() {
52+
# Check for our required `interface` payload value
53+
if (isset($this->initial_data["interface"])) {
54+
$this->initial_data["interface"] = APITools\get_pfsense_if_id($this->initial_data["interface"]);
55+
56+
# Check that the requested interface exists
57+
if ($this->initial_data["interface"]) {
58+
# Check that a traffic shaper is configured for this interface
59+
if ($this->get_shaper_id_by_interface($this->initial_data["interface"], true)) {
60+
# Set the interface this queue will be applied to
61+
$this->parent_id = $this->get_shaper_id_by_interface($this->initial_data["interface"]);
62+
} else {
63+
$this->errors[] = APIResponse\get(4122);
64+
}
65+
} else {
66+
$this->errors[] = APIResponse\get(4111);
67+
}
68+
} else {
69+
$this->errors[] = APIResponse\get(4110);
70+
}
71+
}
72+
73+
private function __validate_name() {
74+
# Check for our required `name` payload value
75+
if (isset($this->initial_data["name"])) {
76+
# Loop through each queue within the interface's shaper and search for a match
77+
foreach ($this->config["shaper"]["queue"][$this->parent_id]["queue"] as $id=>$queue) {
78+
# Check if this queue matches the requested queue to delete
79+
if ($this->initial_data["name"] === $queue["name"]) {
80+
$this->id = intval($id);
81+
$this->validated_data = $this->config["shaper"]["queue"][$this->parent_id]["queue"][$this->id];
82+
}
83+
}
84+
# If no ID was found set does not exist error
85+
if (!isset($this->id)) {
86+
$this->errors[] = APIResponse\get(4145);
87+
}
88+
} else {
89+
$this->errors[] = APIResponse\get(4123);
90+
}
91+
}
92+
93+
public function get_shaper_id_by_interface($interface, $as_bool=false) {
94+
# Loop through each configured shaper
95+
foreach ($this->config["shaper"]["queue"] as $id=>$shaper) {
96+
# Check if this is the shaper for our interface, if so return it's ID
97+
if ($interface === $shaper["interface"]) {
98+
return ($as_bool) ? true : intval($id);
99+
}
100+
}
101+
return ($as_bool) ? false : null;
102+
}
103+
}

tests/test_api_v1_firewall_traffic_shaper_queue.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,18 +415,61 @@ class APIUnitTestFirewallTrafficShaperQueue(unit_test_framework.APIUnitTest):
415415
"realtime3": "1Mb"
416416
}
417417
},
418+
]
419+
delete_tests = [
420+
{
421+
"name": "Delete Test_Queue",
422+
"payload": {
423+
"interface": "lan",
424+
"name": "Test_Queue"
425+
}
426+
},
427+
{
428+
"name": "Check interface requirement",
429+
"status": 400,
430+
"return": 4110
431+
},
432+
{
433+
"name": "Check interface validation",
434+
"status": 400,
435+
"return": 4111,
436+
"payload": {
437+
"interface": "INVALID"
438+
}
439+
},
440+
{
441+
"name": "Check interface with no traffic shaper",
442+
"status": 400,
443+
"return": 4122,
444+
"payload": {
445+
"interface": "wan",
446+
}
447+
},
448+
{
449+
"name": "Check name requirement",
450+
"status": 400,
451+
"return": 4123,
452+
"payload": {
453+
"interface": "lan"
454+
}
455+
},
456+
{
457+
"name": "Check name validation",
458+
"status": 400,
459+
"return": 4145,
460+
"payload": {
461+
"interface": "lan",
462+
"name": "INVALID"
463+
}
464+
},
418465
{
419466
"name": "Delete parent traffic shaper",
420467
"uri": "/api/v1/firewall/traffic_shaper",
421-
"method": "DELETE",
422468
"payload": {
423469
"interface": "lan",
424470
"apply": True
425471
}
426472
},
427-
428473
]
429474

430-
431-
432-
APIUnitTestFirewallTrafficShaperQueue()
475+
APIUnitTestFirewallTrafficShaperQueue()

0 commit comments

Comments
 (0)