diff --git a/filters/openpolicyagent/internal/confighook.go b/filters/openpolicyagent/internal/confighook.go index c9f65b9da6..b26ae390ec 100644 --- a/filters/openpolicyagent/internal/confighook.go +++ b/filters/openpolicyagent/internal/confighook.go @@ -89,25 +89,30 @@ type PrometheusOverride struct { } func (p *PrometheusOverride) OnConfig(ctx context.Context, config *config.Config) (*config.Config, error) { - var ( - statusConfig status.Config - message []byte - ) + return enablePrometheusForStatus(config) +} - if config.Status != nil { - err := json.Unmarshal(config.Status, &statusConfig) - if err != nil { - return nil, err - } +func (p *PrometheusOverride) OnConfigDiscovery(ctx context.Context, config *config.Config) (*config.Config, error) { + return enablePrometheusForStatus(config) +} - statusConfig.Prometheus = true +func enablePrometheusForStatus(config *config.Config) (*config.Config, error) { + if config.Status == nil { + return config, nil + } - message, err = json.Marshal(statusConfig) - if err != nil { - return nil, err - } - config.Status = message + var statusConfig status.Config + if err := json.Unmarshal(config.Status, &statusConfig); err != nil { + return nil, err + } + + statusConfig.Prometheus = true + + message, err := json.Marshal(statusConfig) + if err != nil { + return nil, err } + config.Status = message return config, nil } diff --git a/filters/openpolicyagent/openpolicyagent_test.go b/filters/openpolicyagent/openpolicyagent_test.go index efdd60dd70..d05122b63f 100644 --- a/filters/openpolicyagent/openpolicyagent_test.go +++ b/filters/openpolicyagent/openpolicyagent_test.go @@ -109,7 +109,19 @@ func TestLoadEnvoyMetadata(t *testing.T) { assert.Equal(t, expected, cfg.envoyMetadata) } -func mockControlPlaneWithDiscoveryBundle(discoveryBundle string) (*opasdktest.Server, []byte) { +func mockControlPlaneWithDiscoveryBundle(discoveryBundle string, opts ...ControlPlaneOption) (*opasdktest.Server, []byte) { + cfg := &controlPlaneConfig{ + enableStatus: false, + } + for _, opt := range opts { + opt(cfg) + } + + statusConfig := "" + if cfg.enableStatus { + statusConfig = `,"status":{"console":false, "service": "test"}` + } + opaControlPlane := opasdktest.MustNewServer( opasdktest.MockBundle("/bundles/test", map[string]string{ "main.rego": ` @@ -119,9 +131,7 @@ func mockControlPlaneWithDiscoveryBundle(discoveryBundle string) (*opasdktest.Se `, }), opasdktest.MockBundle("/bundles/discovery", map[string]string{ - "data.json": ` - {"discovery":{"bundles":{"bundles/test":{"persist":false,"resource":"bundles/test","service":"test"}}}} - `, + "data.json": fmt.Sprintf(`{"discovery":{"bundles":{"bundles/test":{"persist":false,"resource":"bundles/test","service":"test"}}%s}}`, statusConfig), }), opasdktest.MockBundle("/bundles/discovery-with-wrong-bundle", map[string]string{ "data.json": ` @@ -1157,6 +1167,60 @@ func TestPrometheusPluginStatusGaugeRegistered(t *testing.T) { assert.True(t, found, "plugin_status_gauge should be registered and have data") } +func TestPrometheusPluginStatusGaugeRegisteredWithDiscovery(t *testing.T) { + _, config := mockControlPlaneWithDiscoveryBundle("bundles/discovery", WithStatusPluginEnabled(true)) + + promRegistry := prometheus.NewRegistry() + opaRegistry, err := NewOpenPolicyAgentRegistry( + WithReuseDuration(1*time.Second), + WithCleanInterval(1*time.Second), + WithOpenPolicyAgentInstanceConfig(WithConfigTemplate(config)), + WithPrometheusRegisterer(promRegistry), + ) + assert.NoError(t, err) + + opaInst, err := opaRegistry.GetOrStartInstance("test") + assert.NoError(t, err) + + // Simulate an HTTP request evaluation + ctx := context.Background() + _, err = opaInst.Eval(ctx, &authv3.CheckRequest{ + Attributes: &authv3.AttributeContext{}, + }) + assert.NoError(t, err) + + // Gather metrics and check for plugin_status_gauge + metricsFamilies, err := promRegistry.Gather() + assert.NoError(t, err) + + found := false + foundLabels := map[string]string{ + "name": "bundle", + "opa_instance_id": "34b78d90-6d9a-4ecc-8ff9-393b9dafa40d", // random ID + "opa_instance_name": "test", + "status": "OK", + } + for _, mf := range metricsFamilies { + if mf.GetName() == "plugin_status_gauge" && len(mf.Metric) > 0 { + if len(mf.Metric) > 0 { + met := mf.Metric[0] + for _, lPair := range met.GetLabel() { + switch lPair.GetName() { + case "opa_instance_id": + found = true // ok, because random ID should always be there + default: + if foundLabels[lPair.GetName()] != lPair.GetValue() { + t.Fatalf("Failed to find label %q: %q, got: %q", lPair.GetName(), foundLabels[lPair.GetName()], lPair.GetValue()) + } + } + } + } + break + } + } + assert.True(t, found, "plugin_status_gauge should be registered and have data for discovery bundle") +} + type opaInstanceStartupTestCase struct { enableCustomControlLoop bool expectedError string