Apisix-dashboard: feat: Route group feature

Created on 24 Nov 2020  ·  48Comments  ·  Source: apache/apisix-dashboard

why

In order to allow users to filter out routes with a specified group from a large number of routes, I propose to add the route groups feature.

how

front-end

In order to finish this feature. There are 3 steps need to do.

  • Adding group options to the edit or create route page.
    image
  • Route group list page
    image

  • Create or Edit route group page
    image

back-end

Create or update API to match front-end requirements.

  • Create route and update route API need to update.
  • Route Group List API.
  • Create and update route group API.

APISIX

Need to discuss how to implement route group requirements.

Free to comment here.

cc @juzhiyuan @liuxiran @gxthrj @nic-chen @membphis

discuss proposal

Most helpful comment

I propose to use the label selection method to achieve group capabilities, Route/upstream and service already have labelattributes, so we can avoid adding the groupId field on the route.

Agree +1.

Refer to the previous discussion https://github.com/apache/apisix-dashboard/issues/431#issuecomment-684139567, and prs: https://github.com/apache/apisix/pull/2279 https://github.com/apache/apisix/pull/2345 , We've already introduced labels in apisix, and labels were originally preparing for group.

Basicly, we need to add group schema to APISIX, and as @gxthrj mentioned, we also need a labelsSelectors mate to do it with labels[1]

The Route data structure would be as follows, (group is not a required attr for a route). we use labels to describe which group is the route in.

{
  "name": "route1",
   ...,
  "labels": {
    ...,
    "group": "group1"
  }
}

{
  "name": "route2",
   ...,
  "labels": {
    "group": "group1"
  }
}

{
  "name": "route3",
   ...,
}

Group data structure would be as follows: (we could also add other selectors for a group).

we use labelSelectors to describe that resources with the selector belong to the group.

{
  "name": "group1",
  "desc": "xxx",
  "labelSelectors": {
    "group": "group1",
  }
}

{
  "name": "group2",
   ...,
  "labelSelectors": {
    "group": "group2",
    "version": "v2",
     ...
  }
}

Reference:

All 48 comments

@liuxiran @membphis Just to make sure, if there will have 1-to-n requirement? (1 route with multiple group)

@liuxiran @membphis Just to make sure, if there will have 1-to-n requirement? (1 route with multiple group)

I think one route only belongs to one group

ok then it looks good to me 👏

I propose to use the label selection method to achieve group capabilities, Route/upstream and service already have labelattributes, so we can avoid adding the groupId field on the route.

But a label is more like to describe what it is, right? 🤔

I would like the way of label, which is more flexible than group.

  • one route allows binding multiple labels

There is a difference here, we should continue discussing this proposal.

If used for management, I prefer to use a separate group id. If it's just for group display, label is a better choice.

The label would be closer to the description but not logic IMHO.

I propose to use the label selection method to achieve group capabilities, Route/upstream and service already have labelattributes, so we can avoid adding the groupId field on the route.

Agree +1.

Refer to the previous discussion https://github.com/apache/apisix-dashboard/issues/431#issuecomment-684139567, and prs: https://github.com/apache/apisix/pull/2279 https://github.com/apache/apisix/pull/2345 , We've already introduced labels in apisix, and labels were originally preparing for group.

Basicly, we need to add group schema to APISIX, and as @gxthrj mentioned, we also need a labelsSelectors mate to do it with labels[1]

The Route data structure would be as follows, (group is not a required attr for a route). we use labels to describe which group is the route in.

{
  "name": "route1",
   ...,
  "labels": {
    ...,
    "group": "group1"
  }
}

{
  "name": "route2",
   ...,
  "labels": {
    "group": "group1"
  }
}

{
  "name": "route3",
   ...,
}

Group data structure would be as follows: (we could also add other selectors for a group).

we use labelSelectors to describe that resources with the selector belong to the group.

{
  "name": "group1",
  "desc": "xxx",
  "labelSelectors": {
    "group": "group1",
  }
}

{
  "name": "group2",
   ...,
  "labelSelectors": {
    "group": "group2",
    "version": "v2",
     ...
  }
}

Reference:

@membphis would you like to share your ideas?

@membphis would you like to share your ideas?

I think @liuxiran 's comment https://github.com/apache/apisix-dashboard/issues/861#issuecomment-734089720 is fine for me.

It is the way I would like.

I think @liuxiran 's comment #861 (comment) is fine for me.

It is the way I would like.

Thanks for your support. If that is ok, I will create the related issue to trace progress.

We can wait for more time, maybe others want to say something

We can wait for more time, maybe others want to say something

ok, that would be better ^-^

It's been four days since the last discussion, should we continue the discussion or prepare for development? @membphis

It's been four days since the last discussion, should we continue the discussion or prepare for development? @membphis

Agree, let's do it ^ _ ^. We can start developing now

Do we need to implement this API in Admin API?

Do we need to implement this API in Admin API?

cc @liuxiran

Do we need to implement this API in Admin API?

It is necessary to increase a group schema in APISIX, and for v2.x we may not rely on the admin api to implement this proposal, so whether add new admin api, needs advice from back-end classmates

cc @membphis @nic-chen @gxthrj @moonming @spacewander

New diagrams based on previous discussions.

  1. Add filter label feature, label field will display on the route list page

image

  1. Add label select feature to the route create(edit) page
    image
    image

cc @membphis @juzhiyuan @liuxiran @nic-chen @gxthrj

Based on previous discussions, we need two apis in manager-api, a API to get label list, and a API to search routes by labels filter.

[
  {"key":  "value"},
  {"key":  "value2"},
  {"key2":  "value3"},
  ...
]
  • Search routes by lables (expand existing interfaces GET /apisix/admin/routes, add query params)
    API name: GET /apisix/admin/routes?label=key:value&label=key:value1&...
    Data: routes list, just keep the same with current data.

cc @LiteSun @membphis @gxthrj @nic-chen @juzhiyuan

Do we need to implement this API in Admin API?

It is necessary to increase a group schema in APISIX, and for v2.x we may not rely on the admin api to implement this proposal, so whether add new admin api, needs advice from back-end classmates

cc @membphis @nic-chen @gxthrj @moonming @spacewander

We should not add new API to admin API anymore.

Hi @liuxiran, we may use a different prefix for the newer API :) How about using something like HOST/api/labels for fetching global label list.

We should not add new API to admin API anymore.

Yep, sorry to forget to synchronize the results of the discussion:

  1. it is not required to modify DP

  2. mananger-api provides the relevant interface (https://github.com/apache/apisix-dashboard/issues/861#issuecomment-738515671)

  3. FE adds a label operation when creating/editing route, and support to search routes by labels. (https://github.com/apache/apisix-dashboard/issues/861#issuecomment-737940323)

Hi @liuxiran, we may use a different prefix for the newer API :) How about using something like HOST/api/labels for fetching global label list.

It looks more reasonable IMO, how about considering making uniform changes in 3.0? @juzhiyuan

Based on previous discussions, we need two apis in manager-api, a API to get label list, and a API to search routes by labels filter.

  • Get label list(create a new API)
    API name: GET /apisix/admin/labels
    Data:
[
  {"key":  "value"},
  {"key":  "value2"},
  {"key2":  "value3"},
  ...
]
  • Search routes by lables (expand existing interfaces GET /apisix/admin/routes, add query params)
    API name: GET /apisix/admin/routes?label=key:value&label=key:value1&...
    Data: routes list, just keep the same with current data.

cc @LiteSun @membphis @gxthrj @nic-chen @juzhiyuan

I think API Get label list also need support search, like:

GET /apisix/admin/labels?label=key&label=key:value&...

User can filter when there are too many labels.

What do you think? @liuxiran

2 things I'm considering.

  1. Our docs don't have that api in the apisix repo.
  2. When we upgrade to 3.0, we only need to convert /apisix/admin to /api for example, then we don't have to wait for 3.0 IMHO.

Let's wait for others' thoughts 😊

I think API Get label list also need support search, like:

GET /apisix/admin/labels?label=key&label=key:value&...

User can filter when there are too many labels.

What do you think? @liuxiran

Agree @nic-chen , that will be more easy to use, and at the same time, we have also considered adding resType to filter lables only belongs to specified res,e.g: routes.

2 things I'm considering.

  1. Our docs don't have that api in the apisix repo.
  2. When we upgrade to 3.0, we only need to convert /apisix/admin to /api for example, then we don't have to wait for 3.0 IMHO.

Let's wait for others' thoughts

Actually, I just don't want to add a new proxy in FE to fit the new prefix ^-^

It doesn't matter to do an interceptor 😃 to prevent from 2 api styles haha

I think API Get label list also need support search, like:
GET /apisix/admin/labels?label=key&label=key:value&...
User can filter when there are too many labels.
What do you think? @liuxiran

Agree @nic-chen , that will be more easy to use, and at the same time, we have also considered adding resType to filter lables only belongs to specified res,e.g: routes.

Agree, resType is needed.

Related issues: #611

2 things I'm considering.

  1. Our docs don't have that api in the apisix repo.
  2. When we upgrade to 3.0, we only need to convert /apisix/admin to /api for example, then we don't have to wait for 3.0 IMHO.

Let's wait for others' thoughts

We will create a new api for get labels,
The origin propsal for new api prefix is in https://github.com/apache/apisix-dashboard/issues/861#issuecomment-738519671
and the referenced comment is from zhiyuan's consideration.

cc @membphis

We will create a new api for get labels,
The origin propsal for new api prefix is in #861 (comment)
and the referenced comment is from zhiyuan's consideration.

cc @membphis

LGTM +1 ^_^

I will replace @liuxuran to implement the related functions of the manager-api. I have two ideas for the function implementation:

  1. At present, the simplest implementation method is to obtain all the route, service and other objects containing labels and traverse them to match the label implementation related functions. However, with the growth of business volume, this may not be the best implementation method.

  2. The second method is to refer to the similar implementation method of indexer of kubernetes to implement a method: label-indexer, which uses the method of key (label): values (obj-tag) to manage the relevant data in memory, and refresh the data through the etcd's watch mechanism. This method is very complex to implement, but I think it's OK for both the user's data volume becoming larger and the subsequent related functions It will be better.

This is my current idea for function implementation. Please see if you have any better suggestions.

thks!

I will replace @liuxuran to implement the related functions of the manager-api. I have two ideas for the function implementation:

  1. At present, the simplest implementation method is to obtain all the route, service and other objects containing labels and traverse them to match the label implementation related functions. However, with the growth of business volume, this may not be the best implementation method.
  2. The second method is to refer to the similar implementation method of indexer of kubernetes to implement a method: label-indexer, which uses the method of key (label): values (obj-tag) to manage the relevant data in memory, and refresh the data through the etcd's watch mechanism. This method is very complex to implement, but I think it's OK for both the user's data volume becoming larger and the subsequent related functions It will be better.

This is my current idea for function implementation. Please see if you have any better suggestions.

thks

After evaluating the implementation plan, it would be more appropriate for my teammate relay to implement it ^-^

and for the implementations outlined above, just wait for others opinion

@gxthrj @membphis @ShiningRush @nic-chen

I will replace @liuxuran to implement the related functions of the manager-api. I have two ideas for the function implementation:

  1. At present, the simplest implementation method is to obtain all the route, service and other objects containing labels and traverse them to match the label implementation related functions. However, with the growth of business volume, this may not be the best implementation method.
  2. The second method is to refer to the similar implementation method of indexer of kubernetes to implement a method: label-indexer, which uses the method of key (label): values (obj-tag) to manage the relevant data in memory, and refresh the data through the etcd's watch mechanism. This method is very complex to implement, but I think it's OK for both the user's data volume becoming larger and the subsequent related functions It will be better.

This is my current idea for function implementation. Please see if you have any better suggestions.
thks

After evaluating the implementation plan, it would be more appropriate for my teammate relay to implement it ^-^

and for the implementations outlined above, just wait for others opinion

@gxthrj @membphis @ShiningRush @nic-chen

My thoughts are consistent with method 2. We have already watched etcd, all fields in memory now.

I will replace @liuxuran to implement the related functions of the manager-api. I have two ideas for the function implementation:

  1. At present, the simplest implementation method is to obtain all the route, service and other objects containing labels and traverse them to match the label implementation related functions. However, with the growth of business volume, this may not be the best implementation method.
  2. The second method is to refer to the similar implementation method of indexer of kubernetes to implement a method: label-indexer, which uses the method of key (label): values (obj-tag) to manage the relevant data in memory, and refresh the data through the etcd's watch mechanism. This method is very complex to implement, but I think it's OK for both the user's data volume becoming larger and the subsequent related functions It will be better.

This is my current idea for function implementation. Please see if you have any better suggestions.
thks

After evaluating the implementation plan, it would be more appropriate for my teammate relay to implement it ^-^

and for the implementations outlined above, just wait for others opinion

@gxthrj @membphis @ShiningRush @nic-chen

Agree with method 2, too.

We should refer to other mature solutions to avoid redevelopment in the future.

Got it, then we will do it in the way of method2.

Method2 is more difficult to implement than method1, it'll take more time. At the same time, @Jaycean has another arrangement this week, we will update the latest progress next week, thanks ^-^

cc @LiteSun @membphis

GET /apisix/admin/labels?label=key&label=key:value&...

This is too simple to use, If we add label for resource, we should also implement label selector as described in here

Based on previous discussions, we need two apis in manager-api, a API to get label list, and a API to search routes by labels filter.

Is there no need to add api to control group resource?
And I think label should be a common feature for all resource not just route

I will replace @liuxuran to implement the related functions of the manager-api. I have two ideas for the function implementation:

  1. At present, the simplest implementation method is to obtain all the route, service and other objects containing labels and traverse them to match the label implementation related functions. However, with the growth of business volume, this may not be the best implementation method.
  2. The second method is to refer to the similar implementation method of indexer of kubernetes to implement a method: label-indexer, which uses the method of key (label): values (obj-tag) to manage the relevant data in memory, and refresh the data through the etcd's watch mechanism. This method is very complex to implement, but I think it's OK for both the user's data volume becoming larger and the subsequent related functions It will be better.

This is my current idea for function implementation. Please see if you have any better suggestions.

thks!

IMO, the first one is not a option, because we do not need to walk all resource, label selector is used for a single resource type and not across resources type.
Then the second one is fine and easy to implement base on current architecture, because we already watch resources to memory cache like k8s apiserver,

Hi, It looks good to me. I can help to implement this if I have the opportunity.

@starsz many thx for you, wait for your PR ^_^

After reading the above discussion and try to implement it for a while.
I design two APIs like the following.

1.
GET /api/labels/:type?{label=key,key:value,key:value}

Type means the specified response e.g: "upstream", "ssl", "service", "consumer".
If type is "all", it means to get all of them.

Because of the lib droplet can't get total values with the same parameters key(Like label=key&label=key:value&label=key2:value2).The solution is that we use , to separate different KV(Like "label=key,key:value,key2:value2").

Response:

[
  {"key":  "value"},
  {"key":  "value2"},
  {"key2":  "value3"},
  ...
]

2.
GET /apisix/admin/routes?label=key,key2:value,key3:value3

Response:

{
    "code":0,
    "message":"",
    "data":{
        "rows":[
         ],
        "total_size":0
    },
    "request_id":"91476327-9ae6-4d33-816d-16f528647d54"
}

BTW, not only the route module has the label option, "upstream", "route", "service", "consumer","ssl" also have.Do we need to implement the API that search by the label?

After reading the above discussion and try to implement it for a while.

I design two APIs like the following.

1.

GET /api/labels/:type?{label=key,key:value,key:value}

Type means the specified response e.g: "upstream", "ssl", "service", "consumer".

If type is "all", it means to get all of them.

Because of the lib droplet can't get total values with the same parameters key(Like label=key&label=key:value&label=key2:value2).The solution is that we use , to separate different KV(Like "label=key,key:value,key2:value2").

Response:

[

  {"key":  "value"},

  {"key":  "value2"},

  {"key2":  "value3"},

  ...

]

2.

GET /apisix/admin/routes?label=key,key2:value,key3:value3

Response:

{

    "code":0,

    "message":"",

    "data":{

        "rows":[

         ],

        "total_size":0

    },

    "request_id":"91476327-9ae6-4d33-816d-16f528647d54"

}

BTW, not only the route module has the label option, "upstream", "route", "service", "consumer","ssl" also have.Do we need to implement the API that search by the label?

I think we need to implement the route search api first(M2.2) then implement others.

Any suggestions about the API design @nic-chen ?

yes, we could just implement the route search api, others could be implemented later. @starsz @LiteSun

FE is not merged now.

Was this page helpful?
0 / 5 - 0 ratings