diff --git a/docs/content/overview/product-telemetry.md b/docs/content/overview/product-telemetry.md index 387421f619..c93e283a15 100644 --- a/docs/content/overview/product-telemetry.md +++ b/docs/content/overview/product-telemetry.md @@ -48,6 +48,7 @@ These are the data points collected and reported by NGINX Ingress Controller: - **WAFPolicies** Number of WAF policies. - **GlobalConfiguration** Represents the use of a GlobalConfiguration resource. - **AppProtectVersion** The AppProtect version +- **IsPlus** Represents whether NGINX is Plus or OSS ## Opt out diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index c87aa1d0d6..43a0c4fb89 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -374,6 +374,7 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc Name: os.Getenv("POD_NAME"), }, Policies: lbc.getAllPolicies, + IsPlus: lbc.isNginxPlus, } collector, err := telemetry.NewCollector( collectorConfig, diff --git a/internal/telemetry/cluster.go b/internal/telemetry/cluster.go index ebc2c7a760..4e3af5167f 100644 --- a/internal/telemetry/cluster.go +++ b/internal/telemetry/cluster.go @@ -197,6 +197,11 @@ func (c *Collector) AppProtectVersion() string { return c.Config.AppProtectVersion } +// IsPlusEnabled returns true or false depending on if NGINX is Plus or OSS +func (c *Collector) IsPlusEnabled() bool { + return c.Config.IsPlus +} + // lookupPlatform takes a string representing a K8s PlatformID // retrieved from a cluster node and returns a string // representing the platform name. diff --git a/internal/telemetry/collector.go b/internal/telemetry/collector.go index 8606ffe2aa..7621d54bba 100644 --- a/internal/telemetry/collector.go +++ b/internal/telemetry/collector.go @@ -74,6 +74,9 @@ type CollectorConfig struct { // AppProtectVersion represents the version of App Protect. AppProtectVersion string + + // IsPlus represents whether NGINX is Plus or OSS + IsPlus bool } // NewCollector takes 0 or more options and creates a new TraceReporter. @@ -137,6 +140,7 @@ func (c *Collector) Collect(ctx context.Context) { GlobalConfiguration: report.GlobalConfiguration, IngressAnnotations: report.IngressAnnotations, AppProtectVersion: report.AppProtectVersion, + IsPlus: report.IsPlus, }, } @@ -178,6 +182,7 @@ type Report struct { GlobalConfiguration bool IngressAnnotations []string AppProtectVersion string + IsPlus bool } // BuildReport takes context, collects telemetry data and builds the report. @@ -248,6 +253,8 @@ func (c *Collector) BuildReport(ctx context.Context) (Report, error) { appProtectVersion := c.AppProtectVersion() + isPlus := c.IsPlusEnabled() + return Report{ Name: "NIC", Version: c.Config.Version, @@ -276,5 +283,6 @@ func (c *Collector) BuildReport(ctx context.Context) (Report, error) { GlobalConfiguration: c.Config.GlobalConfiguration, IngressAnnotations: ingressAnnotations, AppProtectVersion: appProtectVersion, + IsPlus: isPlus, }, err } diff --git a/internal/telemetry/collector_test.go b/internal/telemetry/collector_test.go index b1867f1cdb..308fba89ab 100644 --- a/internal/telemetry/collector_test.go +++ b/internal/telemetry/collector_test.go @@ -389,6 +389,104 @@ func TestCollectPoliciesReport(t *testing.T) { } } +func TestCollectIsPlus(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + isPlus bool + want bool + }{ + { + name: "Plus enabled", + isPlus: true, + want: true, + }, + { + name: "Plus disabled", + isPlus: false, + want: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + buf := &bytes.Buffer{} + exp := &telemetry.StdoutExporter{Endpoint: buf} + + configurator := newConfiguratorWithIngress(t) + + cfg := telemetry.CollectorConfig{ + Configurator: configurator, + K8sClientReader: newTestClientset(node1, kubeNS), + Version: telemetryNICData.ProjectVersion, + IsPlus: tc.isPlus, + } + + c, err := telemetry.NewCollector(cfg, telemetry.WithExporter(exp)) + if err != nil { + t.Fatal(err) + } + c.Collect(context.Background()) + + ver := c.IsPlusEnabled() + + if tc.want != ver { + t.Errorf("want: %t, got: %t", tc.want, ver) + } + }) + } +} + +func TestCollectInvalidIsPlus(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + isPlus bool + want bool + }{ + { + name: "Plus disabled but want enabled", + isPlus: false, + want: true, + }, + { + name: "Plus disabled but want enabled", + isPlus: false, + want: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + buf := &bytes.Buffer{} + exp := &telemetry.StdoutExporter{Endpoint: buf} + + configurator := newConfiguratorWithIngress(t) + + cfg := telemetry.CollectorConfig{ + Configurator: configurator, + K8sClientReader: newTestClientset(node1, kubeNS), + Version: telemetryNICData.ProjectVersion, + IsPlus: tc.isPlus, + } + + c, err := telemetry.NewCollector(cfg, telemetry.WithExporter(exp)) + if err != nil { + t.Fatal(err) + } + c.Collect(context.Background()) + + ver := c.IsPlusEnabled() + + if tc.want == ver { + t.Errorf("want: %t, got: %t", tc.want, ver) + } + }) + } +} + func TestIngressCountReportsNoDeployedIngresses(t *testing.T) { t.Parallel() diff --git a/internal/telemetry/data.avdl b/internal/telemetry/data.avdl index a7a105186a..23c17f4fa1 100644 --- a/internal/telemetry/data.avdl +++ b/internal/telemetry/data.avdl @@ -90,5 +90,8 @@ It is the UID of the `kube-system` Namespace. */ /** AppProtectVersion represents the version of AppProtect. */ string? AppProtectVersion = null; + /** IsPlus represents whether NGINX is Plus or OSS */ + boolean? IsPlus = null; + } } diff --git a/internal/telemetry/exporter.go b/internal/telemetry/exporter.go index db158dd875..ce2dc11e3e 100644 --- a/internal/telemetry/exporter.go +++ b/internal/telemetry/exporter.go @@ -103,4 +103,6 @@ type NICResourceCounts struct { IngressAnnotations []string // AppProtectVersion represents the version of AppProtect. AppProtectVersion string + // IsPlus represents whether NGINX is Plus or OSS + IsPlus bool } diff --git a/internal/telemetry/nicresourcecounts_attributes_generated.go b/internal/telemetry/nicresourcecounts_attributes_generated.go index 75f8eb905d..f215145ad4 100644 --- a/internal/telemetry/nicresourcecounts_attributes_generated.go +++ b/internal/telemetry/nicresourcecounts_attributes_generated.go @@ -32,6 +32,7 @@ func (d *NICResourceCounts) Attributes() []attribute.KeyValue { attrs = append(attrs, attribute.Bool("GlobalConfiguration", d.GlobalConfiguration)) attrs = append(attrs, attribute.StringSlice("IngressAnnotations", d.IngressAnnotations)) attrs = append(attrs, attribute.String("AppProtectVersion", d.AppProtectVersion)) + attrs = append(attrs, attribute.Bool("IsPlus", d.IsPlus)) return attrs }