open-policy-agent/opa

Expose plugin manager options in the SDK config

Closed this issue · 1 comments

What is the underlying problem you're trying to solve?

I am integrating with OPA through its SDK and I have missed the ability to expose the status metrics with prometheus.

If the plugin manager options were exposed to the SDK I could provide a prometheus registry.

Describe the ideal solution

The ideal solution would be to provide a slice of "Manager Options" that would get appended to the list of the default ones that
the SDK already provides.

The SDK client would use it like so:

	opa, err := sdk.New(ctx, sdk.Options{
		ID:           cfg.Authorizer.ID,
		Config:       opaCfg,
		V1Compatible: true,
		Logger:       logging.New(),
                // This is the new option proposed:
		ManagerOpts: []func(*plugins.Manager){
			plugins.WithPrometheusRegister(prometheus.DefaultRegisterer),
		},
	})

Describe a "Good Enough" solution

I believe that the ideal solution proposed seems to be pretty straightforward already.

Additional Context

I have tested this proposed solution locally and could provide a PR with the implementation if the idea is accepted.

The steps I followed were:

Expose this new option in the SDK Options

package sdk

// Options contains parameters to setup and configure OPA.
type Options struct {
	// existing fields were omitted

        // ManagerOpts is a slice of extra manager options
	ManagerOpts []func(*plugins.Manager)
}

Expose the manager options in the opa struct

package sdk

// OPA represents an instance of the policy engine. OPA can be started with
// several options that control configuration, logging, and lifecycle.
type OPA struct {
        // existing fields were omitted
	managerOpts []func(m *plugins.Manager)
}

Use the extra options in the private configure method of the opa struct

package sdk

func (opa *OPA) configure(ctx context.Context, bs []byte, ready chan struct{}, block bool) error {
	info, err := runtime.Term(runtime.Params{Config: opa.config})
	if err != nil {
		return err
	}

	opts := []func(*plugins.Manager){
		plugins.Info(info),
		plugins.Logger(opa.logger),
		plugins.ConsoleLogger(opa.console),
		plugins.EnablePrintStatements(opa.logger.GetLevel() >= logging.Info),
		plugins.PrintHook(loggingPrintHook{logger: opa.logger}),
		plugins.WithHooks(opa.hooks),
	}
	if opa.v1Compatible {
		opts = append(opts, plugins.WithParserOptions(ast.ParserOptions{RegoVersion: ast.RegoV1}))
	}
        // !!! This is where the extra manager options get appended
	for _, extraOpt := range opa.managerOpts {
		opts = append(opts, extraOpt)
	}
	manager, err := plugins.New(
		bs,
		opa.id,
		opa.store,
		opts...,
	)
	if err != nil {
		return err
	}

       // existing code was omitted...
}

This looks like a good change. Feel free to submit a PR. Thanks!