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(konnect): add object counters for Konnect entities #718

Merged
merged 2 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion api/v1alpha1/kongplugin_installation_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ type KongPluginInstallationList struct {
// KongPluginInstallationSpec provides the information necessary to retrieve and install a Kong custom plugin.
// +apireference:kgo:include
type KongPluginInstallationSpec struct {

// The image is an OCI image URL for a packaged custom Kong plugin.
//
// +kubebuilder:validation:Required
Expand Down
42 changes: 42 additions & 0 deletions internal/telemetry/provider_objectcounter_konnect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package telemetry

import (
"github.com/kong/kubernetes-telemetry/pkg/provider"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"

"github.com/kong/gateway-operator/controller/konnect/constraints"
)

// NewObjectCountProvider creates a provider for number of objects in the cluster.
func NewObjectCountProvider[
T constraints.SupportedKonnectEntityType,
TEnt constraints.EntityType[T],
](dyn dynamic.Interface, restMapper meta.RESTMapper, group string, version string) (provider.Provider, error) {
kind := constraints.EntityTypeName[T]()
restMapping, err := restMapper.RESTMapping(
schema.GroupKind{
Group: group,
Kind: kind,
},
version,
)
if err != nil {
return nil, err
}

gvr := schema.GroupVersionResource{
Group: restMapping.Resource.Group,
Version: restMapping.Resource.Version,
Resource: restMapping.Resource.Resource,
}

return provider.NewK8sObjectCountProviderWithRESTMapper(
restMapping.Resource.Resource,
provider.Kind(kind),
dyn,
gvr,
restMapper,
)
}
66 changes: 66 additions & 0 deletions internal/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,23 @@ import (
"github.com/kong/kubernetes-telemetry/pkg/serializers"
"github.com/kong/kubernetes-telemetry/pkg/telemetry"
"github.com/kong/kubernetes-telemetry/pkg/types"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"

operatorv1alpha1 "github.com/kong/gateway-operator/api/v1alpha1"
operatorv1beta1 "github.com/kong/gateway-operator/api/v1beta1"
"github.com/kong/gateway-operator/controller/konnect/constraints"
"github.com/kong/gateway-operator/modules/manager/metadata"
"github.com/kong/gateway-operator/modules/manager/scheme"
k8sutils "github.com/kong/gateway-operator/pkg/utils/kubernetes"

configurationv1 "github.com/kong/kubernetes-configuration/api/configuration/v1"
configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
configurationv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1"
)

const (
Expand Down Expand Up @@ -211,6 +218,41 @@ func createManager(
}
}

if cfg.KonnectControllerEnabled {
{
group, version := configurationv1.GroupVersion.Group, configurationv1.GroupVersion.Version
AddObjectCountProviderOrLog[configurationv1.KongConsumer](w, dyn, cl.RESTMapper(), log, group, version)
}
{
group, version := configurationv1beta1.GroupVersion.Group, configurationv1beta1.GroupVersion.Version
AddObjectCountProviderOrLog[configurationv1beta1.KongConsumerGroup](w, dyn, cl.RESTMapper(), log, group, version)
}
{
group, version := configurationv1alpha1.GroupVersion.Group, configurationv1alpha1.GroupVersion.Version
AddObjectCountProviderOrLog[configurationv1alpha1.KongRoute](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongService](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCredentialACL](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCredentialJWT](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCredentialHMAC](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCredentialAPIKey](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCredentialBasicAuth](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongSNI](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongVault](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCertificate](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongCACertificate](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongDataPlaneClientCertificate](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongKey](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongKeySet](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongPluginBinding](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongTarget](w, dyn, cl.RESTMapper(), log, group, version)
AddObjectCountProviderOrLog[configurationv1alpha1.KongUpstream](w, dyn, cl.RESTMapper(), log, group, version)
}
{
group, version := konnectv1alpha1.GroupVersion.Group, konnectv1alpha1.GroupVersion.Version
AddObjectCountProviderOrLog[konnectv1alpha1.KonnectGatewayControlPlane](w, dyn, cl.RESTMapper(), log, group, version)
}
}

m.AddWorkflow(w)
}
// Add state workflow
Expand Down Expand Up @@ -243,3 +285,27 @@ func createManager(

return m, nil
}

// AddObjectCountProviderOrLog adds a provider for counting objects of the specified
// type to the workflow.
// If this fails to create the provider, it logs the error on Info level (as this
// is not a critical operation).
func AddObjectCountProviderOrLog[
T constraints.SupportedKonnectEntityType,
TEnt constraints.EntityType[T],
](
w telemetry.Workflow,
dyn dynamic.Interface,
restMapper meta.RESTMapper,
log logr.Logger,
group string,
version string,
) {
p, err := NewObjectCountProvider[T, TEnt](dyn, restMapper, group, version)
if err != nil {
log.Info("failed to create object provider", "error", err, "kind", constraints.EntityTypeName[T]())
return
}

w.AddProvider(p)
}
110 changes: 104 additions & 6 deletions internal/telemetry/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,23 @@ import (
operatorv1alpha1 "github.com/kong/gateway-operator/api/v1alpha1"
operatorv1beta1 "github.com/kong/gateway-operator/api/v1beta1"
"github.com/kong/gateway-operator/modules/manager/metadata"

configurationv1 "github.com/kong/kubernetes-configuration/api/configuration/v1"
configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
configurationv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1"
)

func prepareScheme(t *testing.T) *runtime.Scheme {
scheme := runtime.NewScheme()
require.NoError(t, testk8sclient.AddToScheme(scheme))
require.NoError(t, operatorv1beta1.AddToScheme(scheme))
require.NoError(t, operatorv1alpha1.AddToScheme(scheme))
require.NoError(t, configurationv1alpha1.AddToScheme(scheme))
require.NoError(t, configurationv1beta1.AddToScheme(scheme))
require.NoError(t, configurationv1.AddToScheme(scheme))
require.NoError(t, konnectv1alpha1.AddToScheme(scheme))

return scheme
}

Expand Down Expand Up @@ -71,6 +81,38 @@ func createRESTMapper() meta.RESTMapper {
},
meta.RESTScopeNamespace,
)

restMapper.Add(schema.GroupVersionKind{
Group: configurationv1alpha1.SchemeGroupVersion.Group,
Version: configurationv1alpha1.SchemeGroupVersion.Version,
Kind: configurationv1alpha1.KongRoute{}.GetTypeName(),
}, meta.RESTScopeNamespace)
restMapper.Add(schema.GroupVersionKind{
Group: configurationv1alpha1.SchemeGroupVersion.Group,
Version: configurationv1alpha1.SchemeGroupVersion.Version,
Kind: configurationv1alpha1.KongService{}.GetTypeName(),
}, meta.RESTScopeNamespace)
restMapper.Add(schema.GroupVersionKind{
Group: configurationv1alpha1.SchemeGroupVersion.Group,
Version: configurationv1alpha1.SchemeGroupVersion.Version,
Kind: configurationv1alpha1.KongSNI{}.GetTypeName(),
}, meta.RESTScopeNamespace)
restMapper.Add(schema.GroupVersionKind{
Group: configurationv1.SchemeGroupVersion.Group,
Version: configurationv1.SchemeGroupVersion.Version,
Kind: configurationv1.KongConsumer{}.GetTypeName(),
}, meta.RESTScopeNamespace)
restMapper.Add(schema.GroupVersionKind{
Group: configurationv1beta1.SchemeGroupVersion.Group,
Version: configurationv1beta1.SchemeGroupVersion.Version,
Kind: configurationv1beta1.KongConsumerGroup{}.GetTypeName(),
}, meta.RESTScopeNamespace)
restMapper.Add(schema.GroupVersionKind{
Group: konnectv1alpha1.SchemeGroupVersion.Group,
Version: konnectv1alpha1.SchemeGroupVersion.Version,
Kind: konnectv1alpha1.KonnectGatewayControlPlane{}.GetTypeName(),
}, meta.RESTScopeNamespace)

return restMapper
}

Expand Down Expand Up @@ -117,7 +159,7 @@ func TestCreateManager(t *testing.T) {
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
Expand Down Expand Up @@ -153,7 +195,7 @@ func TestCreateManager(t *testing.T) {
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
Expand Down Expand Up @@ -235,7 +277,7 @@ func TestCreateManager(t *testing.T) {
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
Expand Down Expand Up @@ -290,7 +332,7 @@ func TestCreateManager(t *testing.T) {
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
Expand Down Expand Up @@ -324,7 +366,7 @@ func TestCreateManager(t *testing.T) {
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
Expand Down Expand Up @@ -359,7 +401,62 @@ func TestCreateManager(t *testing.T) {
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
{
name: "Konnect entities",
objects: []runtime.Object{
&configurationv1alpha1.KongService{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kong",
Name: "kongservice-1",
},
},
&configurationv1alpha1.KongService{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kong",
Name: "kongservice-2",
},
},
&configurationv1alpha1.KongRoute{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kong",
Name: "kongroute-1",
},
},
&configurationv1.KongConsumer{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kong",
Name: "kongconsumer-1",
},
},
&configurationv1beta1.KongConsumerGroup{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kong",
Name: "kongconsumergroup-1",
},
},
&configurationv1alpha1.KongSNI{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kong",
Name: "kongroute-1",
},
},
},
expectedReportParts: []string{
"signal=test-signal",
"k8s_kongroutes_count=1",
"k8s_kongservices_count=2",
"k8s_kongsnis_count=1",
"k8s_kongconsumers_count=1",
"k8s_kongconsumergroups_count=1",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=true",
"controller_kongplugininstallation_enabled=false",
},
},
Expand Down Expand Up @@ -394,6 +491,7 @@ func TestCreateManager(t *testing.T) {
}
cfg := Config{
DataPlaneControllerEnabled: true,
KonnectControllerEnabled: true,
}

m, err := createManager(
Expand Down
8 changes: 7 additions & 1 deletion modules/manager/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,13 @@ func (m *caManager) maybeCreateCACertificate(ctx context.Context) error {
// a cleanup function and an error.
// The caller is responsible to call the returned function - when the returned
// error is not nil - to stop the reports sending.
func setupAnonymousReports(ctx context.Context, restCfg *rest.Config, logger logr.Logger, metadata metadata.Info, cfg Config) (func(), error) {
func setupAnonymousReports(
ctx context.Context,
restCfg *rest.Config,
logger logr.Logger,
metadata metadata.Info,
cfg Config,
) (func(), error) {
logger.Info("starting anonymous reports")

// NOTE: this is needed to break the import cycle between telemetry and manager packages.
Expand Down
Loading