-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement Target cache hook Targets sometimes need to maintain state about the system. For example, the Gatekeeper target needs to track the set of current Namespaces on the cluster in order to properly match objects to Constraints when Audit is called. This commit adds a Cache interface which Targets may choose to implement. If they implement this interface, Client attempts to add and remove objects from the Target cache just as it does for Driver caches. These operations are not atomic, so it is possible for systems to get into an inconsistent state. There isn't a good solution to this now - I've opened #189 to solve this in the future. The implications are quite complex and there's a lot of edge cases. This commit also modifies the test target handler matchers - they now access the test target's cache in order to function. These matchers aren't called yet - we don't want to break Gatekeeper since Gatekeeper Golang matchers are not yet implemented. Signed-off-by: Will Beason <[email protected]> * Fix merge conflicts Signed-off-by: Will Beason <[email protected]> * Remove ability for caches to fail deleting Otherwise it is easy to get into inconsistent cache states. There's lots of edge cases that can cause unpredictable behaviors that we don't want to allow. Signed-off-by: Will Beason <[email protected]> * Make addition atomic Since adding data can fail in the target cache, remove data from the driver cache. Note that addition/deletion occur in opposite orders for AddData and RemoveData - this is because we want to prioritize reversible over potentially-irreversible operations. Removing data from the handler cache can't fail, so it is safe to add it first. Signed-off-by: Will Beason <[email protected]> * Make it impossible for handler caches to fail deletion Otherwise we can easily end up in very annoying inconsistent states. If deleteion really, really needs to fail then the application should panic rather than allow things to get in an inconsistent state. Per discussion Signed-off-by: Will Beason <[email protected]>
- Loading branch information
Will Beason
authored
Feb 10, 2022
1 parent
bcbf44f
commit cd1085b
Showing
7 changed files
with
362 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package handler | ||
|
||
// Cacher is a type - usually a Handler - which needs to cache state. | ||
// Handlers only need implement this interface if they have need of a cache. | ||
// Handlers which do not implement Cacher are assumed to be stateless from | ||
// Client's perspective. | ||
type Cacher interface { | ||
// GetCache returns the Cache. If nil, the Cacher is treated as having no | ||
// cache. | ||
GetCache() Cache | ||
} | ||
|
||
// Cache is an interface for Handlers to define which allows them to track | ||
// objects not currently under review. For example, this is required to make | ||
// referential constraints work, or to have Constraint match criteria which | ||
// relies on more than just the object under review. | ||
// | ||
// Implementations must satisfy the per-method requirements for Client to handle | ||
// the Cache properly. | ||
type Cache interface { | ||
// Add inserts a new object into Cache with identifier key. If an object | ||
// already exists, replaces the object at key. | ||
Add(key string, object interface{}) error | ||
|
||
// Remove deletes the object at key from Cache. Deletion succeeds if key | ||
// does not exist. | ||
// Remove always succeeds; if for some reason key cannot be deleted the application | ||
// should panic. | ||
Remove(key string) | ||
} | ||
|
||
type NoCache struct{} | ||
|
||
func (n NoCache) Add(key string, object interface{}) error { | ||
return nil | ||
} | ||
|
||
func (n NoCache) Get(key string) (interface{}, error) { | ||
return nil, nil | ||
} | ||
|
||
func (n NoCache) Remove(key string) {} | ||
|
||
var _ Cache = NoCache{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package handlertest | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"sync" | ||
|
||
"github.com/open-policy-agent/frameworks/constraint/pkg/handler" | ||
) | ||
|
||
var ErrInvalidObject = errors.New("invalid object") | ||
|
||
// Cache is a threadsafe Cache for the test Handler which keeps track of | ||
// Namespaces. | ||
type Cache struct { | ||
Namespaces sync.Map | ||
} | ||
|
||
var _ handler.Cache = &Cache{} | ||
|
||
// Add inserts object into Cache if object is a Namespace. | ||
func (c *Cache) Add(key string, object interface{}) error { | ||
obj, ok := object.(*Object) | ||
if !ok { | ||
return fmt.Errorf("%w: got object type %T, want %T", ErrInvalidType, object, &Object{}) | ||
} | ||
|
||
if obj.Name != "" { | ||
return nil | ||
} | ||
|
||
if obj.Namespace == "" { | ||
return fmt.Errorf("%w: must specify one of Name or Namespace", ErrInvalidObject) | ||
} | ||
|
||
c.Namespaces.Store(key, object) | ||
|
||
return nil | ||
} | ||
|
||
func (c *Cache) Remove(key string) { | ||
c.Namespaces.Delete(key) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.