Skip to content

Commit

Permalink
Fix panic issue in resource-metrics (#420)
Browse files Browse the repository at this point in the history
Signed-off-by: Arnob kumar saha <[email protected]>
  • Loading branch information
ArnobKumarSaha authored Apr 9, 2024
1 parent baf126c commit df8e417
Show file tree
Hide file tree
Showing 10 changed files with 511 additions and 4 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
kmodules.xyz/client-go v0.29.13
kmodules.xyz/crd-schema-fuzz v0.29.1
kmodules.xyz/go-containerregistry v0.0.12
kmodules.xyz/resource-metrics v0.29.1
kmodules.xyz/resource-metrics v0.29.4
kmodules.xyz/schema-checker v0.4.1
sigs.k8s.io/cli-utils v0.34.0
sigs.k8s.io/controller-runtime v0.17.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ kmodules.xyz/go-containerregistry v0.0.12 h1:Tl32QGmSqRVm9PUEb/f3dgDeu9zW5fVzt3q
kmodules.xyz/go-containerregistry v0.0.12/go.mod h1:KgeNg0hDsgeda+qc0NzWk0iVRdF0+ZIg/oRzGoYh78I=
kmodules.xyz/offshoot-api v0.29.0 h1:GHLhxxT9jU1N8+FvOCCeJNyU5g0duYS46UGrs6AHNLY=
kmodules.xyz/offshoot-api v0.29.0/go.mod h1:5NxhBblXoDHWStx9HCDJR2KFTwYjEZ7i1Id3jelIunw=
kmodules.xyz/resource-metrics v0.29.1 h1:gP4SNosdDGFImpne52mnQtHacmnllYkTMcYL//p/ltM=
kmodules.xyz/resource-metrics v0.29.1/go.mod h1:OuG/QobZ7o8GFHl/u3lqaUR0fDZDegxtV8Vdh+MNBD4=
kmodules.xyz/resource-metrics v0.29.4 h1:4RmTzmPdlPK2cVCSBC7BVUerXSV//NKMtwZefdU8UW0=
kmodules.xyz/resource-metrics v0.29.4/go.mod h1:OuG/QobZ7o8GFHl/u3lqaUR0fDZDegxtV8Vdh+MNBD4=
kmodules.xyz/schema-checker v0.4.1 h1:V5UEjR6UMAXf307lTgw+9rDRfHLTNA8g/q9DngqYI9M=
kmodules.xyz/schema-checker v0.4.1/go.mod h1:BRXLB3Osuc9raHRJxHOgZFGecZ2aZumLXCHAOa5NPdA=
sigs.k8s.io/cli-utils v0.34.0 h1:zCUitt54f0/MYj/ajVFnG6XSXMhpZ72O/3RewIchW8w=
Expand Down
1 change: 1 addition & 0 deletions vendor/kmodules.xyz/resource-metrics/calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
_ "kmodules.xyz/resource-metrics/batch/v1"
_ "kmodules.xyz/resource-metrics/batch/v1beta1"
_ "kmodules.xyz/resource-metrics/core/v1"
_ "kmodules.xyz/resource-metrics/kafka.kubedb.com/v1alpha1"
_ "kmodules.xyz/resource-metrics/kubedb.com/v1alpha2"
_ "kmodules.xyz/resource-metrics/kubevault.com/v1alpha2"
_ "kmodules.xyz/resource-metrics/ops.kubedb.com/v1alpha1"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
Copyright AppsCode Inc. and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"fmt"

core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"kmodules.xyz/resource-metrics/api"
)

func init() {
api.Register(schema.GroupVersionKind{
Group: "kafka.kubedb.com",
Version: "v1alpha1",
Kind: "ConnectCluster",
}, ConnectCluster{}.ResourceCalculator())
}

type ConnectCluster struct{}

func (r ConnectCluster) ResourceCalculator() api.ResourceCalculator {
return &api.ResourceCalculatorFuncs{
AppRoles: []api.PodRole{api.PodRoleDefault},
RuntimeRoles: []api.PodRole{api.PodRoleDefault, api.PodRoleExporter},
RoleReplicasFn: r.roleReplicasFn,
ModeFn: r.modeFn,
UsesTLSFn: r.usesTLSFn,
RoleResourceLimitsFn: r.roleResourceFn(api.ResourceLimits),
RoleResourceRequestsFn: r.roleResourceFn(api.ResourceRequests),
}
}

func (r ConnectCluster) roleReplicasFn(obj map[string]interface{}) (api.ReplicaList, error) {
replicas, found, err := unstructured.NestedInt64(obj, "spec", "replicas")
if err != nil {
return nil, fmt.Errorf("failed to read spec.replicas %v: %w", obj, err)
}
if !found {
return api.ReplicaList{api.PodRoleDefault: 1}, nil
}
return api.ReplicaList{api.PodRoleDefault: replicas}, nil
}

func (r ConnectCluster) modeFn(obj map[string]interface{}) (string, error) {
replicas, _, err := unstructured.NestedInt64(obj, "spec", "replicas")
if err != nil {
return "", err
}
if replicas > 1 {
return ConnectClusterModeDistributed, nil
}
return ConnectClusterModeStandalone, nil
}

func (r ConnectCluster) usesTLSFn(obj map[string]interface{}) (bool, error) {
_, found, err := unstructured.NestedFieldNoCopy(obj, "spec", "enableSSL")
return found, err
}

func (r ConnectCluster) roleResourceFn(fn func(rr core.ResourceRequirements) core.ResourceList) func(obj map[string]interface{}) (map[api.PodRole]core.ResourceList, error) {
return func(obj map[string]interface{}) (map[api.PodRole]core.ResourceList, error) {
exporter, err := api.ContainerResources(obj, fn, "spec", "monitor", "prometheus", "exporter")
if err != nil {
return nil, err
}
container, replicas, err := api.AppNodeResourcesV2(obj, fn, ConnectClusterContainerName, "spec")
if err != nil {
return nil, err
}
return map[api.PodRole]core.ResourceList{
api.PodRoleDefault: api.MulResourceList(container, replicas),
api.PodRoleExporter: api.MulResourceList(exporter, replicas),
}, nil
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Copyright AppsCode Inc. and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

const (
ConnectClusterModeStandalone = "Standalone"
ConnectClusterModeDistributed = "Distributed"
)

const (
ConnectClusterContainerName = "connect-cluster"
)
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ const (
)

const (
DruidContainerName = "druid"
PgpoolContainerName = "pgpool"
RabbitMQContainerName = "rabbitmq"
SinglestoreContainerName = "singlestore"
SolrContainerName = "solr"
ZooKeeperContainerName = "zookeeper"
)
139 changes: 139 additions & 0 deletions vendor/kmodules.xyz/resource-metrics/kubedb.com/v1alpha2/druid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
Copyright AppsCode Inc. and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha2

import (
"fmt"
"reflect"

"kmodules.xyz/resource-metrics/api"

core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)

func init() {
api.Register(schema.GroupVersionKind{
Group: "kubedb.com",
Version: "v1alpha2",
Kind: "Druid",
}, Druid{}.ResourceCalculator())
}

type Druid struct{}

func (r Druid) ResourceCalculator() api.ResourceCalculator {
return &api.ResourceCalculatorFuncs{
AppRoles: []api.PodRole{api.PodRoleDefault},
RuntimeRoles: []api.PodRole{api.PodRoleDefault, api.PodRoleExporter},
RoleReplicasFn: r.roleReplicasFn,
ModeFn: r.modeFn,
UsesTLSFn: r.usesTLSFn,
RoleResourceLimitsFn: r.roleResourceFn(api.ResourceLimits),
RoleResourceRequestsFn: r.roleResourceFn(api.ResourceRequests),
}
}

func (r Druid) roleReplicasFn(obj map[string]interface{}) (api.ReplicaList, error) {
result := api.ReplicaList{}

topology, found, err := unstructured.NestedMap(obj, "spec", "topology")
if err != nil {
return nil, err
}

if found && topology != nil {
var replicas int64 = 0
for role, roleSpec := range topology {
roleReplicas, found, err := unstructured.NestedInt64(roleSpec.(map[string]interface{}), "replicas")
if err != nil {
return nil, err
}
if found {
result[api.PodRole(role)] = roleReplicas
replicas += roleReplicas
}
}
result[api.PodRoleDefault] = replicas
} else {
// Combined mode
replicas, found, err := unstructured.NestedInt64(obj, "spec", "replicas")
if err != nil {
return nil, fmt.Errorf("failed to read spec.replicas %v: %w", obj, err)
}
if !found {
result[api.PodRoleDefault] = 1
} else {
result[api.PodRoleDefault] = replicas
}
}

return result, nil
}

func (r Druid) modeFn(obj map[string]interface{}) (string, error) {
topology, found, err := unstructured.NestedFieldNoCopy(obj, "spec", "topology")
if err != nil {
return "", err
}
if found && !reflect.ValueOf(topology).IsNil() {
return DBModeDedicated, nil
}
return DBModeCombined, nil
}

func (r Druid) usesTLSFn(obj map[string]interface{}) (bool, error) {
_, found, err := unstructured.NestedFieldNoCopy(obj, "spec", "enableSSL")
return found, err
}

func (r Druid) roleResourceFn(fn func(rr core.ResourceRequirements) core.ResourceList) func(obj map[string]interface{}) (map[api.PodRole]core.ResourceList, error) {
return func(obj map[string]interface{}) (map[api.PodRole]core.ResourceList, error) {
exporter, err := api.ContainerResources(obj, fn, "spec", "monitor", "prometheus", "exporter")
if err != nil {
return nil, err
}

topology, found, err := unstructured.NestedMap(obj, "spec", "topology")
if err != nil {
return nil, err
}
if found && topology != nil {
var replicas int64 = 0
var totalResources core.ResourceList
result := map[api.PodRole]core.ResourceList{}

for role, roleSpec := range topology {
rolePerReplicaResources, roleReplicas, err := api.AppNodeResourcesV2(roleSpec.(map[string]interface{}), fn, DruidContainerName)
if err != nil {
return nil, err
}

roleResources := api.MulResourceList(rolePerReplicaResources, roleReplicas)
result[api.PodRole(role)] = roleResources
totalResources = api.AddResourceList(totalResources, roleResources)
}

result[api.PodRoleDefault] = totalResources
result[api.PodRoleExporter] = api.MulResourceList(exporter, replicas)
return result, nil
}

return nil, nil
}
}
94 changes: 94 additions & 0 deletions vendor/kmodules.xyz/resource-metrics/kubedb.com/v1alpha2/pgpool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
Copyright AppsCode Inc. and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha2

import (
"fmt"

"kmodules.xyz/resource-metrics/api"

core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)

func init() {
api.Register(schema.GroupVersionKind{
Group: "kubedb.com",
Version: "v1alpha2",
Kind: "Pgpool",
}, Pgpool{}.ResourceCalculator())
}

type Pgpool struct{}

func (r Pgpool) ResourceCalculator() api.ResourceCalculator {
return &api.ResourceCalculatorFuncs{
AppRoles: []api.PodRole{api.PodRoleDefault},
RuntimeRoles: []api.PodRole{api.PodRoleDefault, api.PodRoleExporter},
RoleReplicasFn: r.roleReplicasFn,
ModeFn: r.modeFn,
UsesTLSFn: r.usesTLSFn,
RoleResourceLimitsFn: r.roleResourceFn(api.ResourceLimits),
RoleResourceRequestsFn: r.roleResourceFn(api.ResourceRequests),
}
}

func (r Pgpool) roleReplicasFn(obj map[string]interface{}) (api.ReplicaList, error) {
replicas, found, err := unstructured.NestedInt64(obj, "spec", "replicas")
if err != nil {
return nil, fmt.Errorf("failed to read spec.replicas %v: %w", obj, err)
}
if !found {
return api.ReplicaList{api.PodRoleDefault: 1}, nil
}
return api.ReplicaList{api.PodRoleDefault: replicas}, nil
}

func (r Pgpool) modeFn(obj map[string]interface{}) (string, error) {
replicas, _, err := unstructured.NestedInt64(obj, "spec", "replicas")
if err != nil {
return "", err
}
if replicas > 1 {
return DBModeCluster, nil
}
return DBModeStandalone, nil
}

func (r Pgpool) usesTLSFn(obj map[string]interface{}) (bool, error) {
_, found, err := unstructured.NestedFieldNoCopy(obj, "spec", "tls")
return found, err
}

func (r Pgpool) roleResourceFn(fn func(rr core.ResourceRequirements) core.ResourceList) func(obj map[string]interface{}) (map[api.PodRole]core.ResourceList, error) {
return func(obj map[string]interface{}) (map[api.PodRole]core.ResourceList, error) {
container, replicas, err := api.AppNodeResourcesV2(obj, fn, PgpoolContainerName, "spec")
if err != nil {
return nil, err
}

exporter, err := api.ContainerResources(obj, fn, "spec", "monitor", "prometheus", "exporter")
if err != nil {
return nil, err
}
return map[api.PodRole]core.ResourceList{
api.PodRoleDefault: api.MulResourceList(container, replicas),
api.PodRoleExporter: api.MulResourceList(exporter, replicas),
}, nil
}
}
Loading

0 comments on commit df8e417

Please sign in to comment.