Files
releases/server/buffer.go
T
Patrick East 346aa964e8 Add support for multiple bundles
This change brings in support for multiple bundles to be downloaded
and activated OPA.

This is enabled by using the new config option `bundles` to define
the bundles, and deprecates the older `bundle` option.

The new `bundles` keyword and structure is propagated through to the
decision logs, status API, provenance, stored manifests, etc. Check
out the doc changes for all the updated structures.

That being said any existing configuration using `bundle` will *not*
see the new structure, everything is intended to be backwards
compatible (almost to a fault).

Fixes: #721

Signed-off-by: Patrick East <east.patrick@gmail.com>
2019-07-31 03:43:38 -04:00

95 lines
2.1 KiB
Go

// Copyright 2017 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package server
import (
"sync"
"time"
"github.com/open-policy-agent/opa/metrics"
"github.com/open-policy-agent/opa/storage"
"github.com/open-policy-agent/opa/topdown"
)
// Buffer defines an interface that the server can call to push diagnostic
// information about policy decisions. Buffers must be able to handle
// concurrent calls.
type Buffer interface {
// Push adds the given Info into the buffer.
Push(*Info)
// Iter iterates over the buffer, from oldest present Info to newest. It should
// call fn on each Info.
Iter(fn func(*Info))
}
// buffer stores diagnostic information.
type buffer struct {
ring []*Info
size int
start int // The index of the next item to pop.
end int // The index where the next item will be inserted.
sync.Mutex
}
// NewBoundedBuffer creates a new Buffer with maximum size n. NewBoundedBuffer
// will panic if n is not positive.
func NewBoundedBuffer(n int) Buffer {
if n <= 0 {
panic("size must be greater than 0")
}
return &buffer{ring: make([]*Info, n, n)}
}
func (b *buffer) Push(i *Info) {
b.Lock()
defer b.Unlock()
b.ring[b.end] = i
b.end = (b.end + 1) % len(b.ring)
switch b.size {
case len(b.ring): // We erased something, move the start up.
b.start = (b.start + 1) % len(b.ring)
default:
b.size++
}
}
func (b *buffer) Iter(fn func(*Info)) {
b.Lock()
defer b.Unlock()
i := b.start
for j := 0; j < b.size; j++ {
fn(b.ring[i])
i = (i + 1) % len(b.ring)
}
}
// Info contains information describing a policy decision.
type Info struct {
Txn storage.Transaction
Revision string // Deprecated: Use `Bundles` instead
Bundles map[string]BundleInfo
DecisionID string
RemoteAddr string
Query string
Path string
Timestamp time.Time
Input *interface{}
Results *interface{}
Error error
Metrics metrics.Metrics
Trace []*topdown.Event
}
// BundleInfo contains information describing a bundle
type BundleInfo struct {
Revision string
}