Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enterprise: add config map backed history store #1253

Draft
wants to merge 2 commits into
base: dav/expand-store-interface
Choose a base branch
from

Conversation

davidweisse
Copy link
Contributor

This implements the Store interface using Kubernetes Config Maps in preparation for the distributed Coordinator. For now, this can be tested by manually setting the enterprise build tag during the build process.

@davidweisse davidweisse added the no changelog PRs not listed in the release notes label Feb 26, 2025
@@ -105,7 +107,7 @@ func (h *History) GetLatest(pubKey *ecdsa.PublicKey) (*LatestTransition, error)
// verify the transaction signature or return the transaction.
func (h *History) HasLatest() (bool, error) {
if _, err := h.store.Get("transitions/latest"); err != nil {
if errors.Is(err, os.ErrNotExist) {
if errors.Is(err, os.ErrNotExist) || k8serrors.IsNotFound(err) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is leaking implementation details from behind the interface (has been doing so before your change). We could retroactively decide that Get is supposed to return an os.ErrNotExist and do so in the configmapstore. Or add the Has method to the interface. Or add a bool output to Get. I think I'd go with the os error, though.

return &ConfigMapStore{
client: client,
namespace: self.Namespace,
uid: self.GetOwnerReferences()[0].UID,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check the ownerRef for at least the appropriate kind.


// Get the value for key.
func (s *ConfigMapStore) Get(key string) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare a constant for the timeout.

return
case event, ok := <-watcher.ResultChan():
if !ok {
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add a logger to this store, so that we don't just swallow watch errors here and below.

}

func objectName(key string) string {
return fmt.Sprintf("contrast-store-%s-%s", filepath.Dir(key), filepath.Base(key))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that paths always have one level of nesting, and that there's no overlap between dir names (foo/bar-baz vs. foo-bar/baz,). These are probably fine assumptions, but we should at least document the constraints on the interface and enforce them here. "Keys must consist of two alphanumeric identifiers separated by forward slash".

defer cancel()

cm, err := s.client.CoreV1().ConfigMaps(s.namespace).Get(ctx, objectName(key), metav1.GetOptions{})
if err != nil && !(errors.IsNotFound(err) && len(oldVal) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should compare oldVal == nil to distinguish empty value from absent value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no changelog PRs not listed in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants