Bind engine secret handling to facade types
This commit is contained in:
107
internal/engine/secret_binding_test.go
Normal file
107
internal/engine/secret_binding_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Secret is a test-local facade secret. Production engine code must not depend
|
||||
// on this type; each test load supplies the binding below explicitly.
|
||||
type Secret struct {
|
||||
name string
|
||||
value string
|
||||
specified bool
|
||||
resolved bool
|
||||
}
|
||||
|
||||
func SecretEnv(name string) Secret {
|
||||
return Secret{name: name, specified: true}
|
||||
}
|
||||
|
||||
func (s Secret) EnvName() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
func (s Secret) Value() string {
|
||||
if !s.resolved {
|
||||
return ""
|
||||
}
|
||||
return s.value
|
||||
}
|
||||
|
||||
func (s Secret) IsResolved() bool {
|
||||
return s.resolved
|
||||
}
|
||||
|
||||
func (s Secret) Format(state fmt.State, _ rune) {
|
||||
_, _ = io.WriteString(state, "configkit.SecretEnv("+strconv.Quote(s.name)+")")
|
||||
}
|
||||
|
||||
func (s Secret) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(s.name)
|
||||
}
|
||||
|
||||
func testSecretBinding() SecretBinding {
|
||||
return SecretBinding{
|
||||
Type: reflect.TypeFor[Secret](),
|
||||
Read: func(value reflect.Value) SecretState {
|
||||
secret := value.Interface().(Secret)
|
||||
return SecretState{Name: secret.name, Value: secret.value, Specified: secret.specified, Resolved: secret.resolved}
|
||||
},
|
||||
Make: func(state SecretState) reflect.Value {
|
||||
return reflect.ValueOf(Secret{name: state.Name, value: state.Value, specified: state.Specified, resolved: state.Resolved})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testLoad[T any](source Source, supplied ...Options[T]) (*Result[T], error) {
|
||||
return Load(source, testSecretBinding(), supplied...)
|
||||
}
|
||||
|
||||
func testLoadWithSecretLookup[T any](source Source, lookup secretLookup, supplied ...Options[T]) (*Result[T], error) {
|
||||
return loadWithSecretLookup(source, testSecretBinding(), lookup, supplied...)
|
||||
}
|
||||
|
||||
func testBuildSchema(root reflect.Type) (*schemaDescriptor, *schemaIssue) {
|
||||
return buildSchema(root, testSecretBinding())
|
||||
}
|
||||
|
||||
func TestSecretBindingsRemainExactAndIndependent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type otherSecret struct {
|
||||
name string
|
||||
}
|
||||
other := SecretBinding{
|
||||
Type: reflect.TypeFor[otherSecret](),
|
||||
Read: func(value reflect.Value) SecretState {
|
||||
return SecretState{Name: value.Interface().(otherSecret).name}
|
||||
},
|
||||
Make: func(state SecretState) reflect.Value {
|
||||
return reflect.ValueOf(otherSecret{name: state.Name})
|
||||
},
|
||||
}
|
||||
type config struct {
|
||||
First Secret `yaml:"first"`
|
||||
Second otherSecret `yaml:"second"`
|
||||
}
|
||||
firstSchema, firstIssue := buildSchema(reflect.TypeFor[config](), testSecretBinding())
|
||||
if firstIssue != nil {
|
||||
t.Fatal(firstIssue)
|
||||
}
|
||||
secondSchema, secondIssue := buildSchema(reflect.TypeFor[config](), other)
|
||||
if secondIssue != nil {
|
||||
t.Fatal(secondIssue)
|
||||
}
|
||||
firstField := firstSchema.root.fields[firstSchema.root.fieldByName["first"]].descriptor
|
||||
firstOther := firstSchema.root.fields[firstSchema.root.fieldByName["second"]].descriptor
|
||||
secondField := secondSchema.root.fields[secondSchema.root.fieldByName["first"]].descriptor
|
||||
secondOther := secondSchema.root.fields[secondSchema.root.fieldByName["second"]].descriptor
|
||||
if firstField.kind != descriptorSecret || firstOther.kind == descriptorSecret || secondField.kind == descriptorSecret || secondOther.kind != descriptorSecret {
|
||||
t.Fatalf("secret descriptor kinds = %v, %v, %v, %v", firstField.kind, firstOther.kind, secondField.kind, secondOther.kind)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user