Files
opentf/internal/encryption/registry/lockingencryptionregistry/registry.go

80 lines
2.2 KiB
Go

// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package lockingencryptionregistry
import (
"sync"
"github.com/opentofu/opentofu/internal/encryption/keyprovider"
"github.com/opentofu/opentofu/internal/encryption/method"
"github.com/opentofu/opentofu/internal/encryption/registry"
)
// New returns a new encryption registry that locks for parallel access.
func New() registry.Registry {
return &lockingRegistry{
lock: &sync.RWMutex{},
providers: map[keyprovider.ID]keyprovider.Descriptor{},
methods: map[method.ID]method.Descriptor{},
}
}
type lockingRegistry struct {
lock *sync.RWMutex
providers map[keyprovider.ID]keyprovider.Descriptor
methods map[method.ID]method.Descriptor
}
func (l *lockingRegistry) RegisterKeyProvider(keyProvider keyprovider.Descriptor) error {
l.lock.Lock()
defer l.lock.Unlock()
id := keyProvider.ID()
if err := id.Validate(); err != nil {
return &registry.InvalidKeyProviderError{KeyProvider: keyProvider, Cause: err}
}
if _, ok := l.providers[id]; ok {
return &registry.KeyProviderAlreadyRegisteredError{ID: id}
}
l.providers[id] = keyProvider
return nil
}
func (l *lockingRegistry) RegisterMethod(method method.Descriptor) error {
l.lock.Lock()
defer l.lock.Unlock()
id := method.ID()
if err := id.Validate(); err != nil {
return &registry.InvalidMethodError{Method: method, Cause: err}
}
if previousMethod, ok := l.methods[id]; ok {
return &registry.MethodAlreadyRegisteredError{ID: id, CurrentMethod: method, PreviousMethod: previousMethod}
}
l.methods[id] = method
return nil
}
func (l *lockingRegistry) GetKeyProviderDescriptor(id keyprovider.ID) (keyprovider.Descriptor, error) {
l.lock.RLock()
defer l.lock.RUnlock()
provider, ok := l.providers[id]
if !ok {
return nil, &registry.KeyProviderNotFoundError{ID: id}
}
return provider, nil
}
func (l *lockingRegistry) GetMethodDescriptor(id method.ID) (method.Descriptor, error) {
l.lock.RLock()
defer l.lock.RUnlock()
foundMethod, ok := l.methods[id]
if !ok {
return nil, &registry.MethodNotFoundError{ID: id}
}
return foundMethod, nil
}