mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 18:19:04 +02:00
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
102 lines
3.0 KiB
Go
102 lines
3.0 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
// Copyright The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//go:build windows
|
|
|
|
// Package yamlstring decodes configuration file blocks whose value is a YAML or
|
|
// JSON document kept as a string, like the objects of the performancecounter
|
|
// collector.
|
|
package yamlstring
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"go.yaml.in/yaml/v3"
|
|
)
|
|
|
|
// DecodeBlock decodes node, the configuration file block of a collector, into
|
|
// target. key must be the only key of the block, and its value a string holding
|
|
// a YAML or JSON list, the same value the collector's flag takes. A null value
|
|
// leaves target unchanged.
|
|
//
|
|
// Unknown keys, in the block and in the list, are rejected, like everywhere else
|
|
// in the configuration file. The errors are returned as a [yaml.TypeError], so
|
|
// the decoder reports them together with the other errors of the file.
|
|
func DecodeBlock[T any](node *yaml.Node, key string, target *[]T) error {
|
|
if node.Kind != yaml.MappingNode {
|
|
return &yaml.TypeError{Errors: []string{
|
|
fmt.Sprintf("line %d: cannot unmarshal %s into a block with the key %s", node.Line, node.ShortTag(), key),
|
|
}}
|
|
}
|
|
|
|
var errs []string
|
|
|
|
for i := 0; i+1 < len(node.Content); i += 2 {
|
|
name, value := node.Content[i], node.Content[i+1]
|
|
|
|
if name.Value != key {
|
|
errs = append(errs, fmt.Sprintf("line %d: field %s not found, the only field is %s", name.Line, name.Value, key))
|
|
|
|
continue
|
|
}
|
|
|
|
errs = append(errs, decodeValue(value, key, target)...)
|
|
}
|
|
|
|
if len(errs) > 0 {
|
|
return &yaml.TypeError{Errors: errs}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// decodeValue decodes the string value of key into target and returns the
|
|
// errors, if any. Line numbers inside the string count from its first line.
|
|
func decodeValue[T any](value *yaml.Node, key string, target *[]T) []string {
|
|
if value.ShortTag() == "!!null" {
|
|
return nil
|
|
}
|
|
|
|
if value.Kind != yaml.ScalarNode || value.ShortTag() != "!!str" {
|
|
return []string{fmt.Sprintf("line %d: %s must be a string, use %s: |- followed by the list", value.Line, key, key)}
|
|
}
|
|
|
|
decoder := yaml.NewDecoder(strings.NewReader(value.Value))
|
|
decoder.KnownFields(true)
|
|
|
|
var list []T
|
|
|
|
if err := decoder.Decode(&list); err != nil && !errors.Is(err, io.EOF) {
|
|
var typeErr *yaml.TypeError
|
|
if !errors.As(err, &typeErr) {
|
|
return []string{fmt.Sprintf("line %d: in %s, %s", value.Line, key, err)}
|
|
}
|
|
|
|
errs := make([]string, len(typeErr.Errors))
|
|
for i, e := range typeErr.Errors {
|
|
errs[i] = fmt.Sprintf("line %d: in %s, %s", value.Line, key, e)
|
|
}
|
|
|
|
return errs
|
|
}
|
|
|
|
*target = list
|
|
|
|
return nil
|
|
}
|