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

Add Namespaced Group Membership API #5380

Merged
merged 1 commit into from
Aug 29, 2023
Merged

Conversation

qiyueyao
Copy link
Contributor

@qiyueyao qiyueyao commented Aug 10, 2023

Adds membership API for namespaced Group at groupmembers.controlplane.antrea.io. The group association API is still available for both ClusterGroup and namespaced Group.

# curl "<k8s-apiserver>:8001/apis/controlplane.antrea.io/v1beta2/namespaces/<ns>/groupmembers/<name>?page=<page#>&limit=<limit#>"
{
  "kind": "GroupMembers",
  "apiVersion": "controlplane.antrea.io/v1beta2",
  "metadata": {
    "name": "test-group",
    "namespace": "default",
    "creationTimestamp": null
  },
  "effectiveMembers": [
    {
      "pod": {
        "name": "pod1",
        "namespace": "test"
      },
      "ips": [
        "AAAAAAAAAAAAAP//CgoBBg=="
      ]
    }
  ],
  "effectiveIPBlocks": null,
  "totalMembers": 1,
  "totalPages": 1,
  "currentPage": 1
}

Fixes #5269

@qiyueyao qiyueyao force-pushed the group-api branch 3 times, most recently from 0a79296 to 6203a0f Compare August 10, 2023 23:12
@qiyueyao qiyueyao added the area/api Issues or PRs related to an API. label Aug 10, 2023
@qiyueyao qiyueyao added this to the Antrea v1.14 release milestone Aug 10, 2023
@qiyueyao qiyueyao requested review from Dyanngg, tnqn and GraysonWu August 11, 2023 00:16
@qiyueyao qiyueyao requested a review from jianjuns August 17, 2023 13:28
@jianjuns
Copy link
Contributor

Question - I remember we have another API to query Groups given a Pod/ExternalEntity. Do we support that for Namespaced Groups? @qiyueyao @Dyanngg

@Dyanngg
Copy link
Contributor

Dyanngg commented Aug 17, 2023

Question - I remember we have another API to query Groups given a Pod/ExternalEntity. Do we support that for Namespaced Groups? @qiyueyao @Dyanngg

That API already works for namespaced groups

pkg/apiserver/registry/networkpolicy/util.go Outdated Show resolved Hide resolved
pkg/apiserver/registry/networkpolicy/util.go Outdated Show resolved Hide resolved
// PaginateMemberList returns paginated results if meaningful options are provided, options should never be nil.
// Paginated results are continuous only when there is no member change across multiple calls.
// Pagination is not processed if either page number or limit = 0, thus returns full member list.
// Returns an error for invalid options; returns empty list for page number beyond the total pages range.
Copy link
Contributor

Choose a reason for hiding this comment

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

An error is returned for invalid options, and an empty list is returned for a page number out of the pages range.

pkg/apiserver/registry/networkpolicy/util.go Outdated Show resolved Hide resolved
pkg/apiserver/registry/networkpolicy/util.go Outdated Show resolved Hide resolved
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// GroupMembers is a list of GroupMember objects or IPBlocks that are currently selected by a Group.
type GroupMembers struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

This struct is the same as ClusterGroupMembers. Do we need to redefine?

Copy link
Contributor

Choose a reason for hiding this comment

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

And could not we reuse GroupMembers defined in pkg/apis/controlplane/v1beta2/types.go?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I remember controlplane/types.go and v1beta2/types.go where intentionally kept the same, is this outdated?

Copy link
Contributor

Choose a reason for hiding this comment

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

Humm.. I do not know this. Let us see what @tnqn would recommend.

Copy link
Member

Choose a reason for hiding this comment

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

For ClusterGroupMembers and GroupMembers, it's correct to redefine the struct even they are the same because every struct maps its own API, many generated code are based on the struct definition. Besides, it's a convention in K8s API, see https://github.com/kubernetes/kubernetes/blob/fb785f1f42183e26e2b9f042474391c4d58433bb/pkg/apis/rbac/types.go#L109-L120 and https://github.com/kubernetes/kubernetes/blob/fb785f1f42183e26e2b9f042474391c4d58433bb/pkg/apis/rbac/types.go#L174-L186

For controlplane/types.go and v1beta2/types.go, it's also correct to redefine the struct because the former is the internal representation of the data while the latter is the versioned one. The internal representation needs to be convertible with multiple versions so it may change along with the change of the API while the versioned one should remain compatible. For a new API, its internal struct and versioned struct is normally the same but they will diverge when the API evolves. The following docs has more informaiton:
https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// GroupMembers is a list of GroupMember objects or IPBlocks that are currently selected by a Group.
type GroupMembers struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question - why we need to redefine a struct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I redefined because on line 97 // +genclient:nonNamespaced, ClusterGroupMembers API is non namespaced and GroupMembers API is namespaced, and the genclient is auto generated. So I only generalized the pagination function not the Get(). Is there any suggestion to solve the problem? I'm not aware of, thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we do:
type ClusterGroupMember GroupMember?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here? Then they are still not differentiated in terms of nonNamespaced and namespaced 🤔

return nil, errors.NewInternalError(err)
}
// Retrieve options used for pagination.
getOptions, ok := options.(*controlplane.PaginationGetOptions)
Copy link
Contributor

Choose a reason for hiding this comment

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

If we use a shared type for Group and ClusterGroup, we can also share the Get() code with ClusterGroup?

Copy link
Member

Choose a reason for hiding this comment

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

I think we could extract the common code even when there are two different structs. It just needs a function like GetPaginatedMembers(querier groupMembershipQuerier, name string, options runtime.Object) (members []GroupMember, ipNets []IPNet, totalMembers, totalPages, currentPage int64)

Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

LGTM overall

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// GroupMembers is a list of GroupMember objects or IPBlocks that are currently selected by a Group.
type GroupMembers struct {
Copy link
Member

Choose a reason for hiding this comment

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

For ClusterGroupMembers and GroupMembers, it's correct to redefine the struct even they are the same because every struct maps its own API, many generated code are based on the struct definition. Besides, it's a convention in K8s API, see https://github.com/kubernetes/kubernetes/blob/fb785f1f42183e26e2b9f042474391c4d58433bb/pkg/apis/rbac/types.go#L109-L120 and https://github.com/kubernetes/kubernetes/blob/fb785f1f42183e26e2b9f042474391c4d58433bb/pkg/apis/rbac/types.go#L174-L186

For controlplane/types.go and v1beta2/types.go, it's also correct to redefine the struct because the former is the internal representation of the data while the latter is the versioned one. The internal representation needs to be convertible with multiple versions so it may change along with the change of the API while the versioned one should remain compatible. For a new API, its internal struct and versioned struct is normally the same but they will diverge when the API evolves. The following docs has more informaiton:
https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md

return nil, errors.NewInternalError(err)
}
// Retrieve options used for pagination.
getOptions, ok := options.(*controlplane.PaginationGetOptions)
Copy link
Member

Choose a reason for hiding this comment

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

I think we could extract the common code even when there are two different structs. It just needs a function like GetPaginatedMembers(querier groupMembershipQuerier, name string, options runtime.Object) (members []GroupMember, ipNets []IPNet, totalMembers, totalPages, currentPage int64)

}

type groupMembershipQuerier interface {
GetGroupMembersByNamespace(name, namespace string) (controlplane.GroupMemberSet, []controlplane.IPBlock, error)
Copy link
Member

Choose a reason for hiding this comment

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

I feel the "ByNamespace" is a bit misleading. Although making it more accurate like ByNamespacedName could fix it, I wonder if we could just merge the two arguments and just use GetGroupMembers given the callee doesn't need to separate it anyway, we could comment that the method accepts both ClusterGroup name and Group name.

Or we could rename existing GetGroupMembers to GetClusterGroupMembers which takes ClusterGroup name and add GetGroupMembers which takes Group Namespace and Name.

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, generalized GroupMembershipQuerier and the common codes.

@jianjuns jianjuns mentioned this pull request Aug 23, 2023
@qiyueyao qiyueyao force-pushed the group-api branch 2 times, most recently from 2f4e2a8 to 064b669 Compare August 24, 2023 17:51
@qiyueyao qiyueyao requested review from tnqn, Dyanngg and jianjuns August 25, 2023 00:31
func paginateMemberList(memberList *controlplane.ClusterGroupMembers, pageInfo *controlplane.PaginationGetOptions) error {
// Pagination is not enabled if either page number or limit = 0, in which the full member list is returned.
// An error is returned for invalid options, and an empty list is returned for a page number out of the pages range.
func PaginateMemberList(effectiveMembers *[]controlplane.GroupMember, pageInfo *controlplane.PaginationGetOptions) (int64, int64, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Does it need to be public?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, updated.

Currently Antrea supports ClusterGroup and namespaced Group
CRD, but only provides API for ClusterGroup membership.

This solution adds membership API for namespaced Group at
namespacedgroupmembers.controlplane.antrea.io. The group
association API is still available for both ClusterGroup and
namespaced Group.

Fixes antrea-io#5269

Signed-off-by: Qiyue Yao <yaoq@vmware.com>
@qiyueyao
Copy link
Contributor Author

/test-all

Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

LGTM

@tnqn
Copy link
Member

tnqn commented Aug 29, 2023

@jianjuns any other comments? Do we need a pre-release like 1.14.0-alpha.0 for this API?

@jianjuns
Copy link
Contributor

LGTM

@jianjuns jianjuns merged commit 2135110 into antrea-io:main Aug 29, 2023
@qiyueyao qiyueyao deleted the group-api branch October 12, 2023 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api Issues or PRs related to an API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Namespaced Group Membership and Association query API
4 participants