Skip to content

Commit

Permalink
chore: make object counter conditional on CRD existence
Browse files Browse the repository at this point in the history
  • Loading branch information
pmalek committed Oct 8, 2024
1 parent b42d932 commit 201fe02
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 61 deletions.
141 changes: 96 additions & 45 deletions internal/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"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/modules/manager/metadata"
"github.com/kong/gateway-operator/modules/manager/scheme"
k8sutils "github.com/kong/gateway-operator/pkg/utils/kubernetes"
)
Expand All @@ -30,8 +32,19 @@ const (

type Payload = types.ProviderReport

// Config holds the configuration that is sent to telemetry manager.
type Config struct {
DataPlaneControllerEnabled bool
DataPlaneBlueGreenControllerEnabled bool
ControlPlaneControllerEnabled bool
GatewayControllerEnabled bool
KonnectControllerEnabled bool
AIGatewayControllerEnabled bool
KongPluginInstallationEnabled bool
}

// CreateManager creates telemetry manager using the provided rest.Config.
func CreateManager(signal string, restConfig *rest.Config, log logr.Logger, payload Payload) (telemetry.Manager, error) {
func CreateManager(signal string, restConfig *rest.Config, log logr.Logger, meta metadata.Info, cfg Config) (telemetry.Manager, error) {
k, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return nil, fmt.Errorf("failed to create client-go kubernetes client: %w", err)
Expand All @@ -55,7 +68,8 @@ func CreateManager(signal string, restConfig *rest.Config, log logr.Logger, payl
k,
cl,
dyn,
payload,
meta,
cfg,
log,
telemetry.OptManagerPeriod(telemetryPeriod),
)
Expand Down Expand Up @@ -85,7 +99,8 @@ func createManager(
k kubernetes.Interface,
cl client.Client,
dyn dynamic.Interface,
fixedPayload Payload,
meta metadata.Info,
cfg Config,
log logr.Logger,
opts ...telemetry.OptManager,
) (telemetry.Manager, error) {
Expand All @@ -105,71 +120,95 @@ func createManager(
}
// Add cluster state workflow
{
checker := k8sutils.CRDChecker{Client: cl}

cpExists, err := checker.CRDExists(operatorv1beta1.ControlPlaneGVR())
if err != nil {
log.Info("failed to check if controlplane CRD exists", "error", err)
}
aiGatewayExists, err := checker.CRDExists(operatorv1alpha1.AIGatewayGVR())
if err != nil {
log.Info("failed to check if aigateway CRD exists", "error", err)
}
dpExists, err := checker.CRDExists(operatorv1beta1.DataPlaneGVR())
if err != nil {
log.Info("failed to check if dataplane CRD exists", "error", err)
}

w, err := telemetry.NewClusterStateWorkflow(dyn, cl.RESTMapper())
if err != nil {
return nil, fmt.Errorf("failed to create cluster state workflow: %w", err)
}

// Add dataplane count provider to monitor number of dataplanes in the cluster.
p, err := NewDataPlaneCountProvider(dyn, cl.RESTMapper())
if err != nil {
log.Info("failed to create dataplane count provider", "error", err)
} else {
w.AddProvider(p)
if dpExists {
// Add dataplane count provider to monitor number of dataplanes in the cluster.
p, err := NewDataPlaneCountProvider(dyn, cl.RESTMapper())
if err != nil {
log.Info("failed to create dataplane count provider", "error", err)
} else {
w.AddProvider(p)
}
}

// Add controlplane count provider to monitor number of controlplanes in the cluster.
p, err = NewControlPlaneCountProvider(dyn, cl.RESTMapper())
if err != nil {
log.Info("failed to create controlplane count provider", "error", err)
} else {
w.AddProvider(p)
if cpExists {
// Add controlplane count provider to monitor number of controlplanes in the cluster.
p, err := NewControlPlaneCountProvider(dyn, cl.RESTMapper())
if err != nil {
log.Info("failed to create controlplane count provider", "error", err)
} else {
w.AddProvider(p)
}
}

checker := k8sutils.CRDChecker{Client: cl}
// AIGateway is optional so check if it exists before enabling the count provider.
if exists, err := checker.CRDExists(operatorv1alpha1.AIGatewayGVR()); err != nil {
log.Info("failed to check if aigateway CRD exists ", "error", err)
} else if exists {
if aiGatewayExists {
// Add aigateway count provider to monitor number of aigateways in the cluster.
p, err = NewAIgatewayCountProvider(dyn, cl.RESTMapper())
p, err := NewAIgatewayCountProvider(dyn, cl.RESTMapper())
if err != nil {
log.Info("failed to create aigateway count provider", "error", err)
} else {
w.AddProvider(p)
}
}

// Add dataplane count not from gateway.
p, err = NewStandaloneDataPlaneCountProvider(cl)
if err != nil {
log.Info("failed to create standalone dataplane count provider", "error", err)
} else {
w.AddProvider(p)
if dpExists {
// Add dataplane count not from gateway.
p, err := NewStandaloneDataPlaneCountProvider(cl)
if err != nil {
log.Info("failed to create standalone dataplane count provider", "error", err)
} else {
w.AddProvider(p)
}
}

// Add controlplane count not from gateway.
p, err = NewStandaloneControlPlaneCountProvider(cl)
if err != nil {
log.Info("failed to create standalone controlplane count provider", "error", err)
} else {
w.AddProvider(p)
if cpExists {
// Add controlplane count not from gateway.
p, err := NewStandaloneControlPlaneCountProvider(cl)
if err != nil {
log.Info("failed to create standalone controlplane count provider", "error", err)
} else {
w.AddProvider(p)
}
}

// Add dataplane requested replicas count provider to monitor number of requested replicas for dataplanes.
p, err = NewDataPlaneRequestedReplicasCountProvider(cl)
if err != nil {
log.Info("failed to create dataplane requested replicas count provider", "error", err)
} else {
w.AddProvider(p)
if dpExists {
// Add dataplane requested replicas count provider to monitor number of requested replicas for dataplanes.
p, err := NewDataPlaneRequestedReplicasCountProvider(cl)
if err != nil {
log.Info("failed to create dataplane requested replicas count provider", "error", err)
} else {
w.AddProvider(p)
}
}

// Add controlplane requested replicas count provider to monitor number of requested replicas for controlplanes.
p, err = NewControlPlaneRequestedReplicasCountProvider(cl)
if err != nil {
log.Info("failed to create controlplane requested replicas count provider", "error", err)
} else {
w.AddProvider(p)
if cpExists {
// Add controlplane requested replicas count provider to monitor number of requested replicas for controlplanes.
p, err := NewControlPlaneRequestedReplicasCountProvider(cl)
if err != nil {
log.Info("failed to create controlplane requested replicas count provider", "error", err)
} else {
w.AddProvider(p)
}
}

m.AddWorkflow(w)
Expand All @@ -180,7 +219,19 @@ func createManager(
if err != nil {
return nil, fmt.Errorf("failed to create state workflow: %w", err)
} else {
p, err := provider.NewFixedValueProvider("payload", fixedPayload)
payload := Payload{
"v": meta.Release,
"flavor": meta.Flavor,
"controller_dataplane_enabled": cfg.DataPlaneControllerEnabled,
"controller_dataplane_bg_enabled": cfg.DataPlaneBlueGreenControllerEnabled,
"controller_controlplane_enabled": cfg.ControlPlaneControllerEnabled,
"controller_gateway_enabled": cfg.GatewayControllerEnabled,
"controller_konnect_enabled": cfg.KonnectControllerEnabled,
"controller_aigateway_enabled": cfg.AIGatewayControllerEnabled,
"controller_kongplugininstallation_enabled": cfg.KongPluginInstallationEnabled,
}

p, err := provider.NewFixedValueProvider("payload", payload)
if err != nil {
log.Info("failed to create fixed payload provider", "error", err)
} else {
Expand Down
65 changes: 55 additions & 10 deletions internal/telemetry/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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"
)

func prepareScheme(t *testing.T) *runtime.Scheme {
Expand Down Expand Up @@ -91,10 +92,6 @@ func versionInfo() *version.Info {
}

func TestCreateManager(t *testing.T) {
payload := types.ProviderReport{
"v": "0.6.2",
}

testcases := []struct {
name string
objects []runtime.Object
Expand All @@ -116,6 +113,12 @@ func TestCreateManager(t *testing.T) {
"k8s_nodes_count=1",
"k8s_pods_count=0",
"k8s_dataplanes_count=0",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_kongplugininstallation_enabled=false",
},
},
{
Expand Down Expand Up @@ -146,6 +149,12 @@ func TestCreateManager(t *testing.T) {
"k8s_nodes_count=1",
"k8s_pods_count=1",
"k8s_dataplanes_count=1",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_kongplugininstallation_enabled=false",
},
},
{
Expand Down Expand Up @@ -222,6 +231,12 @@ func TestCreateManager(t *testing.T) {
"k8s_controlplanes_count=3",
"k8s_standalone_dataplanes_count=3",
"k8s_standalone_controlplanes_count=2",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_kongplugininstallation_enabled=false",
},
},
{
Expand Down Expand Up @@ -271,6 +286,12 @@ func TestCreateManager(t *testing.T) {
expectedReportParts: []string{
"signal=test-signal",
"k8s_dataplanes_requested_replicas_count=16",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_kongplugininstallation_enabled=false",
},
},
{
Expand Down Expand Up @@ -299,6 +320,12 @@ func TestCreateManager(t *testing.T) {
expectedReportParts: []string{
"signal=test-signal",
"k8s_controlplanes_requested_replicas_count=11",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_kongplugininstallation_enabled=false",
},
},
{
Expand Down Expand Up @@ -328,6 +355,12 @@ func TestCreateManager(t *testing.T) {
"k8s_aigateways_count=0", // NOTE: This does work when run against the cluster.
"k8s_dataplanes_count=1",
"k8s_controlplanes_count=1",
"controller_dataplane_enabled=true",
"controller_dataplane_bg_enabled=false",
"controller_controlplane_enabled=false",
"controller_gateway_enabled=false",
"controller_konnect_enabled=false",
"controller_kongplugininstallation_enabled=false",
},
},
}
Expand Down Expand Up @@ -355,8 +388,16 @@ func TestCreateManager(t *testing.T) {
},
tc.objects...,
)
meta := metadata.Info{
Release: "0.6.2",
Flavor: metadata.OSSFlavor,
}
cfg := Config{
DataPlaneControllerEnabled: true,
}

m, err := createManager(
types.Signal(SignalPing), k8sclient, ctrlClient, dyn, payload,
types.Signal(SignalPing), k8sclient, ctrlClient, dyn, meta, cfg,
logr.Discard(),
telemetry.OptManagerPeriod(time.Hour),
)
Expand All @@ -381,10 +422,6 @@ func TestCreateManager(t *testing.T) {
}

func TestTelemetryUpdates(t *testing.T) {
payload := types.ProviderReport{
"v": "0.6.2",
}

testcases := []struct {
name string
objects []runtime.Object
Expand Down Expand Up @@ -504,8 +541,16 @@ func TestTelemetryUpdates(t *testing.T) {
require.True(t, ok)
d.FakedServerVersion = versionInfo()

meta := metadata.Info{
Release: "0.6.2",
Flavor: metadata.OSSFlavor,
}
cfg := Config{
DataPlaneControllerEnabled: true,
}

m, err := createManager(
types.Signal(SignalPing), k8sclient, ctrlClient, dyn, payload,
types.Signal(SignalPing), k8sclient, ctrlClient, dyn, meta, cfg,
testr.New(t),
telemetry.OptManagerPeriod(time.Hour),
)
Expand Down
17 changes: 11 additions & 6 deletions modules/manager/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func Run(
// Enable anonnymous reporting when configured but not for development builds
// to reduce the noise.
if cfg.AnonymousReports && !cfg.DevelopmentMode {
stopAnonymousReports, err := setupAnonymousReports(ctx, restCfg, setupLog, metadata)
stopAnonymousReports, err := setupAnonymousReports(ctx, restCfg, setupLog, metadata, cfg)
if err != nil {
setupLog.Error(err, "failed setting up anonymous reports")
} else {
Expand Down Expand Up @@ -375,15 +375,20 @@ 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) (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")

payload := telemetry.Payload{
"v": metadata.Release,
"flavor": metadata.Flavor,
// NOTE: this is needed to break the import cycle between telemetry and manager packages.
tCfg := telemetry.Config{
DataPlaneControllerEnabled: cfg.DataPlaneControllerEnabled,
DataPlaneBlueGreenControllerEnabled: cfg.DataPlaneBlueGreenControllerEnabled,
ControlPlaneControllerEnabled: cfg.ControlPlaneControllerEnabled,
GatewayControllerEnabled: cfg.GatewayControllerEnabled,
KonnectControllerEnabled: cfg.KonnectControllersEnabled,
AIGatewayControllerEnabled: cfg.AIGatewayControllerEnabled,
}

tMgr, err := telemetry.CreateManager(telemetry.SignalPing, restCfg, logger, payload)
tMgr, err := telemetry.CreateManager(telemetry.SignalPing, restCfg, logger, metadata, tCfg)
if err != nil {
return nil, fmt.Errorf("failed to create anonymous reports manager: %w", err)
}
Expand Down

0 comments on commit 201fe02

Please sign in to comment.