diff --git a/apis/identity/v1alpha1/openapi_generated.go b/apis/identity/v1alpha1/openapi_generated.go index e58844a4d..ad48a4493 100644 --- a/apis/identity/v1alpha1/openapi_generated.go +++ b/apis/identity/v1alpha1/openapi_generated.go @@ -340,6 +340,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.InboxTokenRequestRequest": schema_resource_metadata_apis_identity_v1alpha1_InboxTokenRequestRequest(ref), "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.InboxTokenRequestResponse": schema_resource_metadata_apis_identity_v1alpha1_InboxTokenRequestResponse(ref), "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.KubernetesInfo": schema_resource_metadata_apis_identity_v1alpha1_KubernetesInfo(ref), + "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeInfo": schema_resource_metadata_apis_identity_v1alpha1_NodeInfo(ref), "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeStats": schema_resource_metadata_apis_identity_v1alpha1_NodeStats(ref), "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.ProductInfo": schema_resource_metadata_apis_identity_v1alpha1_ProductInfo(ref), "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.SelfSubjectNamespaceAccessReview": schema_resource_metadata_apis_identity_v1alpha1_SelfSubjectNamespaceAccessReview(ref), @@ -17249,7 +17250,7 @@ func schema_resource_metadata_apis_identity_v1alpha1_KubernetesInfo(ref common.R "nodeStats": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeStats"), + Ref: ref("kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeInfo"), }, }, }, @@ -17257,7 +17258,65 @@ func schema_resource_metadata_apis_identity_v1alpha1_KubernetesInfo(ref common.R }, }, Dependencies: []string{ - "k8s.io/apimachinery/pkg/version.Info", "kmodules.xyz/client-go/api/v1.ClusterMetadata", "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.ControlPlaneInfo", "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeStats"}, + "k8s.io/apimachinery/pkg/version.Info", "kmodules.xyz/client-go/api/v1.ClusterMetadata", "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.ControlPlaneInfo", "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeInfo"}, + } +} + +func schema_resource_metadata_apis_identity_v1alpha1_NodeInfo(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "count": { + SchemaProps: spec.SchemaProps{ + Type: []string{"integer"}, + Format: "int32", + }, + }, + "capacity": { + SchemaProps: spec.SchemaProps{ + Description: "Capacity represents the total resources of a node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "allocatable": { + SchemaProps: spec.SchemaProps{ + Description: "Allocatable represents the resources of a node that are available for scheduling. Defaults to Capacity.", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"), + }, + }, + }, + }, + }, + "controlPlane": { + SchemaProps: spec.SchemaProps{ + Ref: ref("kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeStats"), + }, + }, + "workers": { + SchemaProps: spec.SchemaProps{ + Ref: ref("kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeStats"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/api/resource.Quantity", "kmodules.xyz/resource-metadata/apis/identity/v1alpha1.NodeStats"}, } } diff --git a/apis/identity/v1alpha1/siteinfo_types.go b/apis/identity/v1alpha1/siteinfo_types.go index 8c0e05942..20da75a84 100644 --- a/apis/identity/v1alpha1/siteinfo_types.go +++ b/apis/identity/v1alpha1/siteinfo_types.go @@ -76,7 +76,7 @@ type KubernetesInfo struct { Cluster *kmapi.ClusterMetadata `json:"cluster,omitempty"` Version *version.Info `json:"version,omitempty"` ControlPlane *ControlPlaneInfo `json:"controlPlane,omitempty"` - NodeStats NodeStats `json:"nodeStats"` + NodeStats NodeInfo `json:"nodeStats"` } // https://github.com/kmodules/client-go/blob/kubernetes-1.16.3/tools/analytics/analytics.go#L66 @@ -89,6 +89,12 @@ type ControlPlaneInfo struct { NotAfter metav1.Time `json:"notAfter"` } +type NodeInfo struct { + NodeStats `json:",inline"` + ControlPlane *NodeStats `json:"controlPlane,omitempty"` + Workers *NodeStats `json:"workers,omitempty"` +} + type NodeStats struct { Count int `json:"count,omitempty"` diff --git a/apis/identity/v1alpha1/zz_generated.deepcopy.go b/apis/identity/v1alpha1/zz_generated.deepcopy.go index b7e34b44a..c6279cce8 100644 --- a/apis/identity/v1alpha1/zz_generated.deepcopy.go +++ b/apis/identity/v1alpha1/zz_generated.deepcopy.go @@ -227,6 +227,33 @@ func (in *KubernetesInfo) DeepCopy() *KubernetesInfo { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeInfo) DeepCopyInto(out *NodeInfo) { + *out = *in + in.NodeStats.DeepCopyInto(&out.NodeStats) + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(NodeStats) + (*in).DeepCopyInto(*out) + } + if in.Workers != nil { + in, out := &in.Workers, &out.Workers + *out = new(NodeStats) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeInfo. +func (in *NodeInfo) DeepCopy() *NodeInfo { + if in == nil { + return nil + } + out := new(NodeInfo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeStats) DeepCopyInto(out *NodeStats) { *out = *in diff --git a/crds/identity.k8s.appscode.com_siteinfos.yaml b/crds/identity.k8s.appscode.com_siteinfos.yaml index 707f72ce8..5415cf5b8 100644 --- a/crds/identity.k8s.appscode.com_siteinfos.yaml +++ b/crds/identity.k8s.appscode.com_siteinfos.yaml @@ -125,8 +125,58 @@ spec: description: 'Capacity represents the total resources of a node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity' type: object + controlPlane: + properties: + allocatable: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Allocatable represents the resources of a node + that are available for scheduling. Defaults to Capacity. + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Capacity represents the total resources of a + node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity' + type: object + count: + type: integer + type: object count: type: integer + workers: + properties: + allocatable: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Allocatable represents the resources of a node + that are available for scheduling. Defaults to Capacity. + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Capacity represents the total resources of a + node. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity' + type: object + count: + type: integer + type: object type: object version: description: 'Info contains versioning information. TODO: Add []string diff --git a/go.mod b/go.mod index 7cb610f02..fc6c05136 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( k8s.io/klog/v2 v2.120.1 k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f kmodules.xyz/apiversion v0.2.0 - kmodules.xyz/client-go v0.30.7 + kmodules.xyz/client-go v0.30.9 kmodules.xyz/crd-schema-fuzz v0.29.1 kmodules.xyz/go-containerregistry v0.0.12 kmodules.xyz/resource-metrics v0.30.1 diff --git a/go.sum b/go.sum index d11203c33..ba46d6c37 100644 --- a/go.sum +++ b/go.sum @@ -340,8 +340,8 @@ k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCf k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kmodules.xyz/apiversion v0.2.0 h1:vAQYqZFm4xu4pbB1cAdHbFEPES6EQkcR4wc06xdTOWk= kmodules.xyz/apiversion v0.2.0/go.mod h1:oPX8g8LvlPdPX3Yc5YvCzJHQnw3YF/X4/jdW0b1am80= -kmodules.xyz/client-go v0.30.7 h1:QcZ3pmyK6YZlqtx1gc8IGK1MyrsapaOW14pc6R7klZA= -kmodules.xyz/client-go v0.30.7/go.mod h1:XL3PDQIXG4s3xNRL2SSxIvi8b2WyMGpn26dFnOBz0j4= +kmodules.xyz/client-go v0.30.9 h1:wiLivFlqVZOitAqLFEa1n53GkbYYOmiR8upjIHPHrYk= +kmodules.xyz/client-go v0.30.9/go.mod h1:XL3PDQIXG4s3xNRL2SSxIvi8b2WyMGpn26dFnOBz0j4= kmodules.xyz/crd-schema-fuzz v0.29.1 h1:zJTlWYOrT5dsVVHW8HGcnR/vaWfxQfNh11QwTtkYpcs= kmodules.xyz/crd-schema-fuzz v0.29.1/go.mod h1:n708z9YQqLMP2KNLQVgBcRJw1QpSWLvpNCEi+KJDOYE= kmodules.xyz/go-containerregistry v0.0.12 h1:Tl32QGmSqRVm9PUEb/f3dgDeu9zW5fVzt3qmAFIE37I= diff --git a/pkg/identity/siteinfo.go b/pkg/identity/siteinfo.go index 69fe6e46b..e0f8f131f 100644 --- a/pkg/identity/siteinfo.go +++ b/pkg/identity/siteinfo.go @@ -23,7 +23,7 @@ import ( clustermeta "kmodules.xyz/client-go/cluster" "kmodules.xyz/client-go/tools/clusterid" - auditorapi "kmodules.xyz/resource-metadata/apis/identity/v1alpha1" + identityapi "kmodules.xyz/resource-metadata/apis/identity/v1alpha1" "kmodules.xyz/resource-metrics/api" "go.bytebuilders.dev/license-verifier/info" @@ -35,26 +35,26 @@ import ( "k8s.io/client-go/rest" ) -func GetSiteInfo(cfg *rest.Config, kc kubernetes.Interface, nodes []*core.Node, licenseID string) (*auditorapi.SiteInfo, error) { - si := auditorapi.SiteInfo{ +func GetSiteInfo(cfg *rest.Config, kc kubernetes.Interface, nodes []*core.Node, licenseID string) (*identityapi.SiteInfo, error) { + si := identityapi.SiteInfo{ TypeMeta: metav1.TypeMeta{ - APIVersion: auditorapi.SchemeGroupVersion.String(), + APIVersion: identityapi.SchemeGroupVersion.String(), Kind: "SiteInfo", }, ObjectMeta: metav1.ObjectMeta{ Name: SelfName, }, - Kubernetes: &auditorapi.KubernetesInfo{}, + Kubernetes: &identityapi.KubernetesInfo{}, } if info.ProductName != "" || v.Version.Version != "" || licenseID != "" { - si.Product = &auditorapi.ProductInfo{} + si.Product = &identityapi.ProductInfo{} si.Product.LicenseID = licenseID si.Product.ProductOwnerName = info.ProductOwnerName si.Product.ProductOwnerUID = info.ProductOwnerUID si.Product.ProductName = info.ProductName si.Product.ProductUID = info.ProductUID - si.Product.Version = auditorapi.Version{ + si.Product.Version = identityapi.Version{ Version: v.Version.Version, VersionStrategy: v.Version.VersionStrategy, CommitHash: v.Version.CommitHash, @@ -81,7 +81,7 @@ func GetSiteInfo(cfg *rest.Config, kc kubernetes.Interface, nodes []*core.Node, if err != nil { return nil, err } else { - si.Kubernetes.ControlPlane = &auditorapi.ControlPlaneInfo{ + si.Kubernetes.ControlPlane = &identityapi.ControlPlaneInfo{ NotBefore: metav1.NewTime(cert.NotBefore), NotAfter: metav1.NewTime(cert.NotAfter), // DNSNames: cert.DNSNames, @@ -143,20 +143,41 @@ func GetSiteInfo(cfg *rest.Config, kc kubernetes.Interface, nodes []*core.Node, return &si, nil } -func RefreshNodeStats(si *auditorapi.SiteInfo, nodes []*core.Node) { +func RefreshNodeStats(si *identityapi.SiteInfo, nodes []*core.Node) { if len(nodes) == 0 { return } - si.Kubernetes.NodeStats.Count = len(nodes) - var capacity core.ResourceList - var allocatable core.ResourceList + var total, cp, w identityapi.NodeStats for _, node := range nodes { - capacity = api.AddResourceList(capacity, node.Status.Capacity) - allocatable = api.AddResourceList(allocatable, node.Status.Allocatable) + total.Count++ + total.Capacity = api.AddResourceList(total.Capacity, node.Status.Capacity) + total.Allocatable = api.AddResourceList(total.Allocatable, node.Status.Allocatable) + + if isControlPlaneNode(node) { + cp.Count++ + cp.Capacity = api.AddResourceList(cp.Capacity, node.Status.Capacity) + cp.Allocatable = api.AddResourceList(cp.Allocatable, node.Status.Allocatable) + } else { + w.Count++ + w.Capacity = api.AddResourceList(w.Capacity, node.Status.Capacity) + w.Allocatable = api.AddResourceList(w.Allocatable, node.Status.Allocatable) + } + } + + si.Kubernetes.NodeStats.NodeStats = total + if cp.Count > 0 { + si.Kubernetes.NodeStats.ControlPlane = &cp } - si.Kubernetes.NodeStats.Capacity = capacity - si.Kubernetes.NodeStats.Allocatable = allocatable + if w.Count > 0 { + si.Kubernetes.NodeStats.Workers = &w + } +} + +func isControlPlaneNode(node *core.Node) bool { + _, okCP := node.Labels["node-role.kubernetes.io/control-plane"] + _, okMaster := node.Labels["node-role.kubernetes.io/master"] + return okCP || okMaster } func skipIP(ip net.IP) bool { diff --git a/vendor/kmodules.xyz/client-go/apiextensions/controller.go b/vendor/kmodules.xyz/client-go/apiextensions/controller.go index b9edf5341..6d3d66a66 100644 --- a/vendor/kmodules.xyz/client-go/apiextensions/controller.go +++ b/vendor/kmodules.xyz/client-go/apiextensions/controller.go @@ -21,6 +21,7 @@ import ( "sync" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -28,8 +29,8 @@ import ( ) type ( - SetupFn func(ctx context.Context, mgr ctrl.Manager) - TestFn func(*apiextensionsv1.CustomResourceDefinition) bool + SetupFn func(context.Context, ctrl.Manager) + TestFn func(meta.RESTMapper, *apiextensionsv1.CustomResourceDefinition) bool ) type setupGroup struct { @@ -77,7 +78,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu if !setupFnExists { return ctrl.Result{}, nil } - if !testFns[gk](&crd) { + if !testFns[gk](r.mgr.GetRESTMapper(), &crd) { return ctrl.Result{}, nil } @@ -111,7 +112,7 @@ func MultiRegisterSetup(gks []schema.GroupKind, fn SetupFn, tn ...TestFn) { mu.Lock() defer mu.Unlock() - testFN := andTestFn(tn...) + testFN := andTestFn(append(tn, allCRDPresent(gks))...) for _, gk := range gks { setupFns[gk] = setupGroup{ gks: gks, @@ -121,10 +122,26 @@ func MultiRegisterSetup(gks []schema.GroupKind, fn SetupFn, tn ...TestFn) { } } +func allCRDPresent(gks []schema.GroupKind) TestFn { + return func(mapper meta.RESTMapper, definition *apiextensionsv1.CustomResourceDefinition) bool { + for _, gk := range gks { + if !crdFound(mapper, gk) { + return false + } + } + return true + } +} + +func crdFound(mapper meta.RESTMapper, gk schema.GroupKind) bool { + _, err := mapper.RESTMappings(gk) + return err == nil +} + func andTestFn(fns ...TestFn) TestFn { - return func(crd *apiextensionsv1.CustomResourceDefinition) bool { + return func(mapper meta.RESTMapper, crd *apiextensionsv1.CustomResourceDefinition) bool { for _, fn := range fns { - if !fn(crd) { + if !fn(mapper, crd) { return false } } diff --git a/vendor/kmodules.xyz/client-go/core/v1/kubernetes.go b/vendor/kmodules.xyz/client-go/core/v1/kubernetes.go index d53222dd6..1b7ed9e41 100644 --- a/vendor/kmodules.xyz/client-go/core/v1/kubernetes.go +++ b/vendor/kmodules.xyz/client-go/core/v1/kubernetes.go @@ -79,6 +79,15 @@ func GetContainerByName(containers []core.Container, name string) *core.Containe return nil } +func GetContainerIdByName(containers []core.Container, name string) int { + for i := range containers { + if containers[i].Name == name { + return i + } + } + return -1 +} + func UpsertContainer(containers []core.Container, upsert core.Container) []core.Container { for i, container := range containers { if container.Name == upsert.Name { diff --git a/vendor/modules.txt b/vendor/modules.txt index 6119d6199..9e476eaa9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -716,7 +716,7 @@ k8s.io/utils/trace # kmodules.xyz/apiversion v0.2.0 ## explicit; go 1.14 kmodules.xyz/apiversion -# kmodules.xyz/client-go v0.30.7 +# kmodules.xyz/client-go v0.30.9 ## explicit; go 1.22.0 kmodules.xyz/client-go kmodules.xyz/client-go/api/v1