Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: validate the subordinate and check reference when deleting and adding… #8219

Closed

Conversation

biakewe
Copy link
Contributor

@biakewe biakewe commented Oct 31, 2022

…route

Description

   Add two logics related to subordinate route。
   1  validate if the stream route with superior id exists and its protocol matches the subordinate
       solve it by core.log.warn() 
   2  when deleting a stream route, check if it is referenced by another stream route
       add the referenced relation  in res.body

Fixes #6939

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

@biakewe biakewe changed the title validate the subordinate and check reference when deleting a stream … feat: validate the subordinate and check reference when deleting a stream … Oct 31, 2022
Copy link
Member

@spacewander spacewander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@biakewe
Copy link
Contributor Author

biakewe commented Nov 1, 2022

I want to ask a question :

core.etcd.set("/apisix/stream_routes/refer/12",{"/apisix/stream_routes/22":1})
---->
/apisix/stream_routes/refer/12
"{"\/apisix\/stream_routes\/22":1}"

Is additional serialization required?

Can you give me some pointers? @spacewander

@tzssangglass
Copy link
Member

core.etcd.set("/apisix/stream_routes/refer/12",{"/apisix/stream_routes/22":1})
---->
/apisix/stream_routes/refer/12
"{"/apisix/stream_routes/22":1}"

read more: api7/lua-resty-etcd#180 (comment)

@biakewe
Copy link
Contributor Author

biakewe commented Nov 2, 2022

core.etcd.set("/apisix/stream_routes/refer/12",{"/apisix/stream_routes/22":1})
---->
/apisix/stream_routes/refer/12
"{"/apisix/stream_routes/22":1}"

read more: api7/lua-resty-etcd#180 (comment)

@biakewe biakewe closed this Nov 2, 2022
@biakewe biakewe reopened this Nov 2, 2022
@biakewe
Copy link
Contributor Author

biakewe commented Nov 2, 2022

Some problems have been changed; thank for the review, and hope to communicate @spacewander @tzssangglass

@spacewander
Copy link
Member

Please make the test & lint pass, like:
https://github.com/apache/apisix/actions/runs/3376629320/jobs/5619505907

Error: led test 't/admin/stream-routes.t TEST 17:  return reference info, DELETE - pattern "[error]" should not match any line in error.log but matches line "2022/11/03 06:56:19 [error] 40724#40724: *55 lua entry thread aborted: runtime error: /home/runner/work/apisix/apisix/apisix/core/config_util.lua:38: attempt to index local 'tab' (a nil value)" (req 0)
# stack traceback:
# coroutine 0:
# 	/home/runner/work/apisix/apisix/apisix/core/config_util.lua: in function '(for generator)'
# 	...runner/work/apisix/apisix/apisix/admin/stream_routes.lua:35: in function 'check_router_refer'
# 	...runner/work/apisix/apisix/apisix/admin/stream_routes.lua:195: in function <...runner/work/apisix/apisix/apisix/admin/stream_routes.lua:187>
# 	/home/runner/work/apisix/apisix/apisix/admin/init.lua:188: in function 'handler'
# 	...ork/apisix/apisix/deps/share/lua/5.1/resty/radixtree.lua:723: in function 'dispatch'
# 	/home/runner/work/apisix/apisix/apisix/init.lua:821: in function 'http_admin'

https://github.com/apache/apisix/actions/runs/3376629320/jobs/5619505955

Error: led test 't/stream-node/sni.t TEST 13: clean up routes - pattern "[error]" should not match any line in error.log but matches line "2022/11/03 06:55:54 [error] 44683#44683: *63 lua entry thread aborted: runtime error: /home/runner/work/apisix/apisix/apisix/core/config_util.lua:38: attempt to index local 'tab' (a nil value)" (req 0)
# stack traceback:
# coroutine 0:
# 	/home/runner/work/apisix/apisix/apisix/core/config_util.lua: in function '(for generator)'
# 	...runner/work/apisix/apisix/apisix/admin/stream_routes.lua:35: in function 'check_router_refer'
# 	...runner/work/apisix/apisix/apisix/admin/stream_routes.lua:195: in function <...runner/work/apisix/apisix/apisix/admin/stream_routes.lua:187>
# 	/home/runner/work/apisix/apisix/apisix/admin/init.lua:188: in function 'handler'
# 	...ork/apisix/apisix/deps/share/lua/5.1/resty/radixtree.lua:723: in function 'dispatch'
# 	/home/runner/work/apisix/apisix/apisix/init.lua:821: in function 'http_admin'

@biakewe
Copy link
Contributor Author

biakewe commented Nov 3, 2022

please approve running workflows @spacewander

@@ -639,3 +639,30 @@ passed
{"error_msg":"property \"faults\" validation failed: wrong type: expected array, got string"}
--- no_error_log
[error]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need three blank lines between test cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

local referkey = "/stream_routes_refer/" .. id
local _, err = core.etcd.delete(referkey)
core.log.warn(err)
core.log.warn(items)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
core.log.warn(items)
core.log.info("items:", core.json.delay_encode(items))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

local refer_list = {}
local referkey = "/stream_routes_refer/" .. id
local _, err = core.etcd.delete(referkey)
core.log.warn(err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the err here only printed and not processed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleting a stream route, check if it is referenced by another stream route ; before query ,delete previous value and then generate new。 Just delete previous , I choose to ignore exceptions handle because I can't think of errors happening

else
core.log.error("In function check_router_refer error: ", err)
end
local setres, err = core.etcd.set(setkey, data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid writing this data to etcd. You set here, I don't see where we delete key. so stream_routes_refer will grow forever?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keys stream_routes_refer/super_ids will be update rather than grow .
ex:

/apisix/stream_routes_refer/12
{"_apisix_stream_routes_22":1,"_apisix_stream_routes_23":1}

it meas the stream_route 22 and 23 have protocol.superior_id 12; if the stream_routes rule no change ,the value no change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so at what point do we delete /apisix/stream_routes_refer/12?

Anyway, I don't think it's a good solution to write this relationship to etcd.

Can we refer to the logic for removing the upstream?

if services_ver and services then
for _, service in ipairs(services) do
if type(service) == "table" and service.value
and service.value.upstream_id
and tostring(service.value.upstream_id) == id then
return 400, {error_msg = "can not delete this upstream,"
.. " service [" .. service.value.id
.. "] is still using it now"}
end
end
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your suggestion I changed the implementation.

if route.protocol and route.protocol.superior_id then
local data
local setkey = "/stream_routes_refer/" .. route.protocol.superior_id
local res, err = core.etcd.get(setkey, false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to filter the data by superior_id in etcd every time when we delete an item like this? That might be very inefficient.

Copy link
Contributor Author

@biakewe biakewe Nov 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For generate the reference-relationship while iterating over the items(stream_routes), only the data by superior_id exists reference-relationship.
thanks for your suggestion。

@biakewe biakewe force-pushed the check-the-subordinate-relationship branch from dac6b2b to 94cdf53 Compare November 5, 2022 07:35
if item.value == nil then
goto CONTINUE
end
local r_id = string.gsub(item["key"], "/", "_")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we replace string.gsub with ngx.re.gsub?

@biakewe
Copy link
Contributor Author

biakewe commented Nov 17, 2022

I successfully tested locally:

-----request
curl http://127.0.0.1:9180/apisix/admin/stream_routes/22 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"server_port": 9100,
"upstream": {
"type": "none",
"nodes": {
"192.168.31.170:6379": 1
}
},
"protocol": {
"name": "redis",
"superior_id": "1",
"conf": {
"faults": [{
"commands": ["get", "ping"],
"delay": 5
}]
}
}
}
'
curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE

-----response
{"key":"/apisix/stream_routes/22","value":{"update_time":1668671546,"upstream":{"nodes":{"192.168.31.170:6379":1},"scheme":"http","type":"none","hash_on":"vars","pass_host":"pass"},"protocol":{"name":"redis","superior_id":"1","conf":{"faults":[{"delay":5,"commands":["get","ping"]}]}},"id":"22","create_time":1668668955,"server_port":9100}}
/stream_routes/1 is referred by /apisix/stream_routes/22

I didn't find the reason for the failure in stream_routes.t,please help to see what happened

@@ -78,6 +102,14 @@ local function check_conf(id, conf, need_id)
return need_id and id or true
end

function _M.stream_routes()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about moving the init (stream_init_worker) to

?

We should only initialize it when stream_proxy is enabled:

if not local_conf.apisix.stream_proxy then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified,please have a look

Comment on lines 152 to 154
core.config.init()
local router_stream = require("apisix.stream.router.ip_port")
router_stream.stream_init_worker(filter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here: #8219 (comment) means move router_stream.stream_init_worker(filter) to function _M.init_worker(), not local function run().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

tzssangglass
tzssangglass previously approved these changes Nov 18, 2022
@@ -19,6 +19,7 @@ local core = require("apisix.core")
local route = require("apisix.utils.router")
local plugin = require("apisix.plugin")
local v3_adapter = require("apisix.admin.v3_adapter")
local filter = require("apisix.router").filter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to export filter first so we can use it:

local function filter(route)

tzssangglass
tzssangglass previously approved these changes Nov 21, 2022
@@ -14,6 +14,7 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local filter = require("apisix.router").filter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does module apisix.router export the function filter?
BTW, the require call should be put under local require = require.

@@ -15,6 +15,7 @@
-- limitations under the License.
--
local require = require
local filter = require("apisix.router").filter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does module "apisix.router" export the filter function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry

@@ -354,7 +353,7 @@ function _M.init_worker()

if local_conf.apisix.stream_proxy then
local router_stream = require("apisix.stream.router.ip_port")
router_stream.stream_init_worker(filter)
router_stream.stream_init_worker()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to export the filter and pass it into stream_init_worker, otherwise, the data structure may be different.

@github-actions
Copy link

This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the [email protected] list. Thank you for your contributions.

@github-actions github-actions bot added the stale label Jan 24, 2023
@github-actions
Copy link

This pull request/issue has been closed due to lack of activity. If you think that is incorrect, or the pull request requires review, you can revive the PR at any time.

@github-actions github-actions bot closed this Mar 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: As a user, I want to check the subordinate relationship in the Admin API
3 participants