Index secret failure locations lazily
This commit is contained in:
@@ -21,6 +21,22 @@ type secretResolutionResult struct {
|
||||
diagnostics []Diagnostic
|
||||
}
|
||||
|
||||
type secretReferenceLocationResolver struct {
|
||||
input *document.Node
|
||||
lookup *documentLookup
|
||||
}
|
||||
|
||||
func (resolver *secretReferenceLocationResolver) diagnostic(code Code, path Path, message string) Diagnostic {
|
||||
if resolver.lookup == nil {
|
||||
resolver.lookup = buildDocumentLookup(resolver.input)
|
||||
}
|
||||
diagnostic := Diagnostic{Code: code, Severity: SeverityError, Path: path.clone(), Message: message}
|
||||
if location, ok := nearestDocumentLocationWithLookup(resolver.input, path, resolver.lookup); ok {
|
||||
diagnostic.Primary = documentLocationPointer(location)
|
||||
}
|
||||
return diagnostic
|
||||
}
|
||||
|
||||
func resolveSecretReferences(root reflect.Value, schema *schemaDescriptor, input *document.Node, lookup secretLookup) secretResolutionResult {
|
||||
result := secretResolutionResult{
|
||||
lookups: make(map[string]secretLookupResult), references: make(map[string]string),
|
||||
@@ -32,17 +48,18 @@ func resolveSecretReferences(root reflect.Value, schema *schemaDescriptor, input
|
||||
if lookup == nil {
|
||||
lookup = func(string) (string, bool) { return "", false }
|
||||
}
|
||||
resolveSecretValue(root, schema.root, schema.secrets, Path{}, false, input, lookup, &result)
|
||||
locations := &secretReferenceLocationResolver{input: input}
|
||||
resolveSecretValue(root, schema.root, schema.secrets, Path{}, false, locations, lookup, &result)
|
||||
result.diagnostics = canonicalDiagnostics(result.diagnostics)
|
||||
return result
|
||||
}
|
||||
|
||||
func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets SecretBinding, path Path, optional bool, input *document.Node, lookup secretLookup, result *secretResolutionResult) {
|
||||
func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets SecretBinding, path Path, optional bool, locations *secretReferenceLocationResolver, lookup secretLookup, result *secretResolutionResult) {
|
||||
if descriptor.kind == descriptorPointer {
|
||||
if value.IsNil() {
|
||||
return
|
||||
}
|
||||
resolveSecretValue(value.Elem(), descriptor.element, secrets, path, descriptor.element.kind == descriptorSecret, input, lookup, result)
|
||||
resolveSecretValue(value.Elem(), descriptor.element, secrets, path, descriptor.element.kind == descriptorSecret, locations, lookup, result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -57,11 +74,11 @@ func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets
|
||||
code = CodeSecretInvalidName
|
||||
message = "secret environment name is empty"
|
||||
}
|
||||
result.diagnostics = append(result.diagnostics, secretDiagnostic(code, path, message, input))
|
||||
result.diagnostics = append(result.diagnostics, locations.diagnostic(code, path, message))
|
||||
return
|
||||
}
|
||||
if !validEnvironmentName(name) {
|
||||
result.diagnostics = append(result.diagnostics, secretDiagnostic(CodeSecretInvalidName, path, "secret environment name is invalid", input))
|
||||
result.diagnostics = append(result.diagnostics, locations.diagnostic(CodeSecretInvalidName, path, "secret environment name is invalid"))
|
||||
return
|
||||
}
|
||||
found, exists := result.lookups[name]
|
||||
@@ -70,11 +87,11 @@ func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets
|
||||
result.lookups[name] = found
|
||||
}
|
||||
if !found.present {
|
||||
result.diagnostics = append(result.diagnostics, secretDiagnostic(CodeSecretUnset, path, "secret environment variable is not set", input))
|
||||
result.diagnostics = append(result.diagnostics, locations.diagnostic(CodeSecretUnset, path, "secret environment variable is not set"))
|
||||
return
|
||||
}
|
||||
if found.value == "" {
|
||||
result.diagnostics = append(result.diagnostics, secretDiagnostic(CodeSecretEmpty, path, "secret environment variable is empty", input))
|
||||
result.diagnostics = append(result.diagnostics, locations.diagnostic(CodeSecretEmpty, path, "secret environment variable is empty"))
|
||||
return
|
||||
}
|
||||
value.Set(secrets.Make(SecretState{Name: name, Value: found.value, Specified: true, Resolved: true}))
|
||||
@@ -85,7 +102,7 @@ func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets
|
||||
if !member.inline {
|
||||
memberPath = path.Key(member.name)
|
||||
}
|
||||
resolveSecretValue(value.Field(member.index), member.descriptor, secrets, memberPath, false, input, lookup, result)
|
||||
resolveSecretValue(value.Field(member.index), member.descriptor, secrets, memberPath, false, locations, lookup, result)
|
||||
}
|
||||
case descriptorMap:
|
||||
if value.IsNil() {
|
||||
@@ -96,7 +113,7 @@ func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets
|
||||
for _, key := range keys {
|
||||
entry := reflect.New(value.Type().Elem()).Elem()
|
||||
entry.Set(value.MapIndex(key))
|
||||
resolveSecretValue(entry, descriptor.element, secrets, path.Key(key.String()), false, input, lookup, result)
|
||||
resolveSecretValue(entry, descriptor.element, secrets, path.Key(key.String()), false, locations, lookup, result)
|
||||
value.SetMapIndex(key, entry)
|
||||
}
|
||||
case descriptorSlice, descriptorArray:
|
||||
@@ -104,19 +121,11 @@ func resolveSecretValue(value reflect.Value, descriptor *typeDescriptor, secrets
|
||||
return
|
||||
}
|
||||
for index := 0; index < value.Len(); index++ {
|
||||
resolveSecretValue(value.Index(index), descriptor.element, secrets, path.Index(index), false, input, lookup, result)
|
||||
resolveSecretValue(value.Index(index), descriptor.element, secrets, path.Index(index), false, locations, lookup, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func secretDiagnostic(code Code, path Path, message string, input *document.Node) Diagnostic {
|
||||
diagnostic := Diagnostic{Code: code, Severity: SeverityError, Path: path.clone(), Message: message}
|
||||
if location, ok := nearestDocumentLocation(input, path); ok {
|
||||
diagnostic.Primary = documentLocationPointer(location)
|
||||
}
|
||||
return diagnostic
|
||||
}
|
||||
|
||||
func changedSecretStates(root reflect.Value, schema *schemaDescriptor, lookups map[string]secretLookupResult) []Path {
|
||||
var changed []Path
|
||||
if schema == nil || schema.root == nil {
|
||||
|
||||
Reference in New Issue
Block a user