From 8025fde0c0b385f7a9f2263e035b2a095c091066 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Fri, 22 Sep 2023 17:37:00 -0700 Subject: [PATCH] Remove most of selfdescribe package --- .../pkg/selfdescribe/metadata.go | 3 +- .../pkg/selfdescribe/monitors.go | 145 ------------ .../signalfx-agent/pkg/selfdescribe/notes.go | 64 ------ .../pkg/selfdescribe/observers.go | 210 ------------------ .../pkg/selfdescribe/reflect.go | 94 -------- .../pkg/selfdescribe/selfdescribe.go | 39 ---- .../pkg/selfdescribe/sourcedocs.go | 132 ----------- .../pkg/selfdescribe/structs.go | 82 ------- .../signalfx-agent/pkg/selfdescribe/types.go | 20 -- 9 files changed, 1 insertion(+), 788 deletions(-) delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/monitors.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/notes.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/observers.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/reflect.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/selfdescribe.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/sourcedocs.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/structs.go delete mode 100644 internal/signalfx-agent/pkg/selfdescribe/types.go diff --git a/internal/signalfx-agent/pkg/selfdescribe/metadata.go b/internal/signalfx-agent/pkg/selfdescribe/metadata.go index 65159a3968..cae793a223 100644 --- a/internal/signalfx-agent/pkg/selfdescribe/metadata.go +++ b/internal/signalfx-agent/pkg/selfdescribe/metadata.go @@ -2,7 +2,6 @@ package selfdescribe import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -79,7 +78,7 @@ func CollectMetadata(root string) ([]PackageMetadata, error) { var pkg PackageMetadata - if bytes, err := ioutil.ReadFile(path); err != nil { + if bytes, err := os.ReadFile(path); err != nil { return fmt.Errorf("unable to read metadata file %s: %w", path, err) } else if err := yaml.UnmarshalStrict(bytes, &pkg); err != nil { return fmt.Errorf("unable to unmarshal file %s: %w", path, err) diff --git a/internal/signalfx-agent/pkg/selfdescribe/monitors.go b/internal/signalfx-agent/pkg/selfdescribe/monitors.go deleted file mode 100644 index fc0162b1a6..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/monitors.go +++ /dev/null @@ -1,145 +0,0 @@ -package selfdescribe - -import ( - "go/doc" - "reflect" - "sort" - "strconv" - - log "github.com/sirupsen/logrus" - - "github.com/signalfx/signalfx-agent/pkg/monitors" -) - -type monitorDoc struct { - MonitorMetadata - Config structMetadata `json:"config"` - AcceptsEndpoints bool `json:"acceptsEndpoints"` - SingleInstance bool `json:"singleInstance"` -} - -func monitorsStructMetadata() []monitorDoc { - sms := []monitorDoc{} - // Set to track undocumented monitors - monTypesSeen := map[string]bool{} - - if packages, err := CollectMetadata("pkg/monitors"); err != nil { - log.Fatal(err) - } else { - for _, pkg := range packages { - for _, monitor := range pkg.Monitors { - monType := monitor.MonitorType - - if _, ok := monitors.ConfigTemplates[monType]; !ok { - log.Errorf("Found metadata for %s monitor in %s but it doesn't appear to be registered", - monType, pkg.Path) - continue - } - t := reflect.TypeOf(monitors.ConfigTemplates[monType]).Elem() - monTypesSeen[monType] = true - - checkSendAllLogic(monType, monitor.Metrics, monitor.SendAll) - checkDuplicateMetrics(pkg.Path, monitor.Metrics) - checkMetricTypes(pkg.Path, monitor.Metrics) - - if monitor.Groups == nil { - monitor.Groups = make(map[string]*GroupMetadata) - } - - for name, metric := range monitor.Metrics { - group := "" - if metric.Group != nil { - group = *metric.Group - } - - if monitor.Groups[group] == nil { - monitor.Groups[group] = &GroupMetadata{} - } - - groupMeta := monitor.Groups[group] - groupMeta.Metrics = append(groupMeta.Metrics, name) - sort.Strings(groupMeta.Metrics) - } - - mc, _ := t.FieldByName("MonitorConfig") - mmd := monitorDoc{ - Config: getStructMetadata(t), - MonitorMetadata: MonitorMetadata{ - SendAll: monitor.SendAll, - SendUnknown: monitor.SendUnknown, - NoneIncluded: monitor.NoneIncluded, - MonitorType: monType, - Dimensions: monitor.Dimensions, - Groups: monitor.Groups, - Metrics: monitor.Metrics, - Properties: monitor.Properties, - Doc: monitor.Doc, - }, - AcceptsEndpoints: mc.Tag.Get("acceptsEndpoints") == strconv.FormatBool(true), - SingleInstance: mc.Tag.Get("singleInstance") == strconv.FormatBool(true), - } - mmd.Config.Package = pkg.PackagePath - - sms = append(sms, mmd) - } - } - } - - sort.Slice(sms, func(i, j int) bool { - return sms[i].MonitorType < sms[j].MonitorType - }) - - for k := range monitors.ConfigTemplates { - if !monTypesSeen[k] { - log.Warnf("Monitor Type %s is registered but does not appear to have documentation", k) - } - } - - return sms -} - -func dimensionsFromNotes(allDocs []*doc.Package) map[string]DimMetadata { - dm := map[string]DimMetadata{} - for _, note := range notesFromDocs(allDocs, "DIMENSION") { - dm[note.UID] = DimMetadata{ - Description: commentTextToParagraphs(note.Body), - } - } - return dm -} - -func checkDuplicateMetrics(path string, metrics map[string]MetricMetadata) { - seen := map[string]bool{} - - for metric := range metrics { - if seen[metric] { - log.Errorf("duplicate metric '%s' found in %s", metric, path) - } - seen[metric] = true - } -} - -func checkMetricTypes(path string, metrics map[string]MetricMetadata) { - for metric, info := range metrics { - t := info.Type - if t != "gauge" && t != "counter" && t != "cumulative" { - log.Errorf("Bad metric type '%s' for metric %s in %s", t, metric, path) - } - } -} - -func checkSendAllLogic(monType string, metrics map[string]MetricMetadata, sendAll bool) { - if len(metrics) == 0 { - return - } - - hasDefault := false - for _, metricInfo := range metrics { - hasDefault = hasDefault || metricInfo.Default - } - if hasDefault && sendAll { - log.Warnf("sendAll was specified on monitor type '%s' but some metrics were also marked as 'default'", monType) - } else if !hasDefault && !sendAll { - log.Warnf("sendAll was not specified on monitor type '%s' and no metrics are marked as 'default'", monType) - } -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/notes.go b/internal/signalfx-agent/pkg/selfdescribe/notes.go deleted file mode 100644 index 3e8232db85..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/notes.go +++ /dev/null @@ -1,64 +0,0 @@ -package selfdescribe - -import ( - "go/ast" - "go/doc" - "regexp" -) - -// Go's go/doc package has a note parser that collapses all whitespace to a -// single space instead of just letting the output renderer decide whether to -// keep the output or not. Therefore, we have to copy/paste the note parsing -// code here and remove the whitespace normalization so that it is more useful. - -var ( - noteMarker = `([A-Z][A-Z_-]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char - noteMarkerRx = regexp.MustCompile(`^[ \t]*` + noteMarker) // MARKER(uid) at text start - noteCommentRx = regexp.MustCompile(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start -) - -// readNote collects a single note from a sequence of comments. -func readNote(list []*ast.Comment, notes map[string][]*doc.Note) { - text := (&ast.CommentGroup{List: list}).Text() - if m := noteMarkerRx.FindStringSubmatchIndex(text); m != nil { - // The note body starts after the marker. - // We remove any formatting so that we don't - // get spurious line breaks/indentation when - // showing the TODO body. - body := text[m[1]:] - if body != "" { - marker := text[m[2]:m[3]] - notes[marker] = append(notes[marker], &doc.Note{ - Pos: list[0].Pos(), - End: list[len(list)-1].End(), - UID: text[m[4]:m[5]], - Body: body, - }) - } - } -} - -// readNotes extracts notes from comments. -// A note must start at the beginning of a comment with "MARKER(uid):" -// and is followed by the note body (e.g., "// BUG(gri): fix this"). -// The note ends at the end of the comment group or at the start of -// another note in the same comment group, whichever comes first. -func readNotes(comments []*ast.CommentGroup) map[string][]*doc.Note { - notes := make(map[string][]*doc.Note) - for _, group := range comments { - i := -1 // comment index of most recent note start, valid if >= 0 - list := group.List - for j, c := range list { - if noteCommentRx.MatchString(c.Text) { - if i >= 0 { - readNote(list[i:j], notes) - } - i = j - } - } - if i >= 0 { - readNote(list[i:], notes) - } - } - return notes -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/observers.go b/internal/signalfx-agent/pkg/selfdescribe/observers.go deleted file mode 100644 index 5370526248..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/observers.go +++ /dev/null @@ -1,210 +0,0 @@ -package selfdescribe - -import ( - "go/doc" - "os" - "path/filepath" - "reflect" - "sort" - "strings" - - log "github.com/sirupsen/logrus" - - "github.com/signalfx/signalfx-agent/pkg/core/services" - "github.com/signalfx/signalfx-agent/pkg/observers" -) - -type observerMetadata struct { - structMetadata - ObserverType string `json:"observerType"` - Dimensions map[string]DimMetadata `json:"dimensions"` - EndpointVariables []endpointVar `json:"endpointVariables"` -} - -type endpointVar struct { - Name string `json:"name"` - Type string `json:"type"` - ElementKind string `json:"elementKind"` - Description string `json:"description"` -} - -func observersStructMetadata() ([]observerMetadata, error) { - sms := []observerMetadata{} - // Set to track undocumented observers - obsTypesSeen := make(map[string]bool) - - err := filepath.Walk("pkg/observers", func(path string, info os.FileInfo, err error) error { - if !info.IsDir() || err != nil { - return err - } - pkgDoc := packageDoc(path) - if pkgDoc == nil { - return nil - } - for obsType, obsDoc := range observerDocsInPackage(pkgDoc) { - if _, ok := observers.ConfigTemplates[obsType]; !ok { - log.Errorf("Found OBSERVER doc for observer type %s but it doesn't appear to be registered", obsType) - continue - } - t := reflect.TypeOf(observers.ConfigTemplates[obsType]).Elem() - obsTypesSeen[obsType] = true - - allDocs, err := nestedPackageDocs(path) - if err != nil { - return err - } - - dims, err := dimensionsFromNotesAndServicesPackage(allDocs) - if err != nil { - return err - } - - endpointVars, err := endpointVariables(allDocs) - if err != nil { - return err - } - - mmd := observerMetadata{ - structMetadata: getStructMetadata(t), - ObserverType: obsType, - Dimensions: dims, - EndpointVariables: endpointVars, - } - mmd.Doc = obsDoc - mmd.Package = path - - sms = append(sms, mmd) - } - return nil - }) - if err != nil { - return nil, err - } - - sort.Slice(sms, func(i, j int) bool { - return sms[i].ObserverType < sms[j].ObserverType - }) - - for k := range observers.ConfigTemplates { - if !obsTypesSeen[k] { - log.Warnf("Observer Type %s is registered but does not appear to have documentation", k) - } - } - - return sms, nil -} - -func observerDocsInPackage(pkgDoc *doc.Package) map[string]string { - out := make(map[string]string) - for _, note := range pkgDoc.Notes["OBSERVER"] { - out[note.UID] = note.Body - } - return out -} - -func dimensionsFromNotesAndServicesPackage(allDocs []*doc.Package) (map[string]DimMetadata, error) { - containerDims := map[string]DimMetadata{} - - if isContainerObserver(allDocs) { - servicesDocs, err := nestedPackageDocs("pkg/core/services") - if err != nil { - return nil, err - } - - for _, note := range notesFromDocs(servicesDocs, "CONTAINER_DIMENSION") { - containerDims[note.UID] = DimMetadata{ - Description: commentTextToParagraphs(note.Body), - } - } - } - - for k, v := range dimensionsFromNotes(allDocs) { - containerDims[k] = v - } - - return containerDims, nil -} - -func isContainerObserver(obsDocs []*doc.Package) bool { - obsEndpointTypes := notesFromDocs(obsDocs, "ENDPOINT_TYPE") - - if len(obsEndpointTypes) > 0 && obsEndpointTypes[0].UID == "ContainerEndpoint" { - return true - } - return false -} - -func endpointVariables(obsDocs []*doc.Package) ([]endpointVar, error) { - servicesDocs, err := nestedPackageDocs("pkg/core/services") - if err != nil { - return nil, err - } - - var eType reflect.Type - isForContainers := isContainerObserver(obsDocs) - if isForContainers { - eType = reflect.TypeOf(services.ContainerEndpoint{}) - } else { - eType = reflect.TypeOf(services.EndpointCore{}) - } - sm := getStructMetadata(eType) - - return append( - endpointVariablesFromNotes(append(obsDocs, servicesDocs...), isForContainers), - endpointVarsFromStructMetadataFields(sm.Fields)...), nil -} - -func endpointVarsFromStructMetadataFields(fields []fieldMetadata) []endpointVar { - var endpointVars []endpointVar - for _, fm := range fields { - if fm.ElementStruct != nil { - endpointVars = append(endpointVars, endpointVarsFromStructMetadataFields(fm.ElementStruct.Fields)...) - continue - } - - endpointVars = append(endpointVars, endpointVar{ - Name: fm.YAMLName, - Type: fm.Type, - ElementKind: fm.ElementKind, - Description: fm.Doc, - }) - } - sort.Slice(endpointVars, func(i, j int) bool { - return endpointVars[i].Name < endpointVars[j].Name - }) - return endpointVars -} - -func endpointVariablesFromNotes(allDocs []*doc.Package, includeContainerVars bool) []endpointVar { - var endpointVars []endpointVar - for _, note := range notesFromDocs(allDocs, "ENDPOINT_VAR") { - uidSplit := strings.Split(note.UID, "|") - typ := "string" - if len(uidSplit) > 1 { - typ = uidSplit[1] - } - - endpointVars = append(endpointVars, endpointVar{ - Name: uidSplit[0], - Type: typ, - Description: commentTextToParagraphs(note.Body), - }) - } - - // This is pretty hacky but is about the cleanest way to distinguish - // container derived variables from non-container vars so that docs aren't - // misleading. - if includeContainerVars { - for _, note := range notesFromDocs(allDocs, "CONTAINER_ENDPOINT_VAR") { - endpointVars = append(endpointVars, endpointVar{ - Name: note.UID, - Type: "string", - Description: commentTextToParagraphs(note.Body), - }) - } - } - sort.Slice(endpointVars, func(i, j int) bool { - return endpointVars[i].Name < endpointVars[j].Name - }) - return endpointVars -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/reflect.go b/internal/signalfx-agent/pkg/selfdescribe/reflect.go deleted file mode 100644 index c65070fa43..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/reflect.go +++ /dev/null @@ -1,94 +0,0 @@ -package selfdescribe - -import ( - "encoding/json" - "reflect" - "strconv" - "strings" - - log "github.com/sirupsen/logrus" - yaml "gopkg.in/yaml.v2" -) - -// Only works if there is an explicit "yaml" struct tag -func getYAMLName(f reflect.StructField) string { - yamlTag := f.Tag.Get("yaml") - return strings.SplitN(yamlTag, ",", 2)[0] -} - -func isInlinedYAML(f reflect.StructField) bool { - return strings.Contains(f.Tag.Get("yaml"), ",inline") -} - -// Assumes monitors are using the defaults package -func getDefault(f reflect.StructField) interface{} { - if getRequired(f) { - return nil - } - if f.Tag.Get("noDefault") == strconv.FormatBool(true) { - return nil - } - - defTag := f.Tag.Get("default") - if defTag != "" { - // These are essentially just noop defaults so don't return them - if defTag == "{}" || defTag == "[]" { - return "" - } - if strings.HasPrefix(defTag, "{") || strings.HasPrefix(defTag, "[") || defTag == strconv.FormatBool(true) || defTag == strconv.FormatBool(false) { - var out interface{} - err := json.Unmarshal([]byte(defTag), &out) - if err != nil { - log.WithError(err).Warnf("Could not unmarshal default value `%s` for field %s", defTag, f.Name) - return defTag - } - return out - } - if asInt, err := strconv.Atoi(defTag); err == nil { - return asInt - } - return defTag - } - if f.Type.Kind() == reflect.Ptr { - if f.Type.Elem().Kind() == reflect.Bool { - return "false" - } - return nil - } - if f.Type.Kind() != reflect.Struct { - return reflect.Zero(f.Type).Interface() - } - return nil -} - -// Assumes that monitors are using the validate package to do validation -func getRequired(f reflect.StructField) bool { - validate := f.Tag.Get("validate") - for _, v := range strings.Split(validate, ",") { - if v == "required" { - return true - } - } - return false -} - -// The kind with any pointer removed -func indirectKind(t reflect.Type) reflect.Kind { - if t == reflect.TypeOf(yaml.MapSlice(nil)) { - return reflect.Map - } - - kind := t.Kind() - if kind == reflect.Ptr { - return t.Elem().Kind() - } - return kind -} - -// The type with any pointers removed -func indirectType(t reflect.Type) reflect.Type { - if t.Kind() == reflect.Ptr { - return t.Elem() - } - return t -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/selfdescribe.go b/internal/signalfx-agent/pkg/selfdescribe/selfdescribe.go deleted file mode 100644 index 7f2bd513cb..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/selfdescribe.go +++ /dev/null @@ -1,39 +0,0 @@ -// Package selfdescribe contains code that knows how to pull metadata from -// various agent component out into a well structured format that can be fed -// into other workflows to generate documentation or other resources such as -// chef recipies. The main interface is the JSON() function, that returns -// everything encoded as JSON. -package selfdescribe - -import ( - "encoding/json" - "io" - "reflect" - - "github.com/signalfx/signalfx-agent/pkg/core/config" - "github.com/signalfx/signalfx-agent/pkg/core/config/sources" -) - -// JSON returns a json encoded string of all of the documentation for the -// various components in the agent. It is meant to be used as an intermediate -// form which serves as a data source for automatically generating docs about -// the agent. -func JSON(writer io.Writer) { - osm, err := observersStructMetadata() - if err != nil { - panic(err) - } - - out, err := json.MarshalIndent(map[string]interface{}{ - "TopConfig": getStructMetadata(reflect.TypeOf(config.Config{})), - "GenericMonitorConfig": getStructMetadata(reflect.TypeOf(config.MonitorConfig{})), - "GenericObserverConfig": getStructMetadata(reflect.TypeOf(config.ObserverConfig{})), - "Monitors": monitorsStructMetadata(), - "Observers": osm, - "SourceConfig": getStructMetadata(reflect.TypeOf(sources.SourceConfig{})), - }, "", " ") - if err != nil { - panic(err) - } - _, _ = writer.Write(out) -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/sourcedocs.go b/internal/signalfx-agent/pkg/selfdescribe/sourcedocs.go deleted file mode 100644 index d20f0e8e53..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/sourcedocs.go +++ /dev/null @@ -1,132 +0,0 @@ -package selfdescribe - -import ( - "fmt" - "go/ast" - "go/doc" - "go/parser" - "go/token" - "os" - "path/filepath" - "regexp" - "strings" -) - -type astCacheEntry struct { - fset *token.FileSet - pkgs map[string]*ast.Package -} - -// nolint: gochecknoglobals -// Used to cache the asts parsed from package files -var astCache = map[string]astCacheEntry{} - -// Returns the ast node of the struct itself and the comment group on the -// struct type. -func structNodes(packageDir, structName string) (*ast.TypeSpec, *ast.CommentGroup) { - var fset *token.FileSet - var pkgs map[string]*ast.Package - - cached, ok := astCache[packageDir] - if ok { - fset = cached.fset - pkgs = cached.pkgs - } else { - fset = token.NewFileSet() - var err error - pkgs, err = parser.ParseDir(fset, packageDir, nil, parser.ParseComments) - if err != nil { - panic(err) - } - astCache[packageDir] = astCacheEntry{fset: fset, pkgs: pkgs} - } - - for _, p := range pkgs { - for _, f := range p.Files { - // Find the struct specified by structName by looking at all nodes - // with comments. This means that the config struct has to have a - // comment on it or else it won't be found. - cmap := ast.NewCommentMap(fset, f, f.Comments) - for node := range cmap { - if t, ok := node.(*ast.GenDecl); ok { - if t.Tok != token.TYPE { - continue - } - - if t.Specs[0].(*ast.TypeSpec).Name.Name == structName { - return t.Specs[0].(*ast.TypeSpec), t.Doc - } - } - } - } - } - panic(fmt.Sprintf("Could not find %s in %s", structName, packageDir)) -} - -func structDoc(packageDir, structName string) string { - _, commentGroup := structNodes(packageDir, structName) - return commentTextToParagraphs(commentGroup.Text()) -} - -func packageDoc(packageDir string) *doc.Package { - fset := token.NewFileSet() - pkgs, err := parser.ParseDir(fset, packageDir, nil, parser.ParseComments) - if err != nil { - panic(err) - } - if len(pkgs) > 1 { - panic("Can't handle multiple packages") - } - if len(pkgs) == 0 { - return nil - } - p := pkgs[filepath.Base(packageDir)] - // go/doc is pretty inflexible in how it parses notes so do it ourselves. - notes := readNotes(ast.MergePackageFiles(p, 0).Comments) - pkgDoc := doc.New(p, packageDir, doc.AllDecls|doc.AllMethods) - pkgDoc.Notes = notes - return pkgDoc -} - -func nestedPackageDocs(packageDir string) ([]*doc.Package, error) { - var out []*doc.Package - err := filepath.Walk(packageDir, func(path string, info os.FileInfo, err error) error { - if !info.IsDir() || err != nil { - return err - } - - pkgDoc := packageDoc(path) - if pkgDoc != nil { - out = append(out, pkgDoc) - } - return nil - }) - return out, err -} - -func notesFromDocs(docs []*doc.Package, noteType string) []*doc.Note { - var notes []*doc.Note - for _, pkgDoc := range docs { - notes = append(notes, pkgDoc.Notes[noteType]...) - } - return notes -} - -func structFieldDocs(packageDir, structName string) map[string]string { - configStruct, _ := structNodes(packageDir, structName) - fieldDocs := map[string]string{} - for _, field := range configStruct.Type.(*ast.StructType).Fields.List { - if field.Names != nil { - fieldDocs[field.Names[0].Name] = commentTextToParagraphs(field.Doc.Text()) - } - } - - return fieldDocs -} - -// nolint: gochecknoglobals -var textRE = regexp.MustCompile(`([^\n])\n([^\s])`) - -func commentTextToParagraphs(t string) string { - return strings.TrimSpace(textRE.ReplaceAllString(t, "$1 $2")) -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/structs.go b/internal/signalfx-agent/pkg/selfdescribe/structs.go deleted file mode 100644 index 262c3c3196..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/structs.go +++ /dev/null @@ -1,82 +0,0 @@ -package selfdescribe - -import ( - "reflect" - "strings" - - "gopkg.in/yaml.v2" -) - -// Embedded structs to always ignore since they already provided in other -// places in the output. -var excludedFields = map[string]bool{ - "MonitorConfig": true, - "ObserverConfig": true, - "OtherConfig": true, -} - -// This will have to change if we start pulling in monitors from other repos -func packageDirOfType(t reflect.Type) string { - return strings.TrimPrefix(t.PkgPath(), "github.com/signalfx/signalfx-agent/") -} - -func getStructMetadata(typ reflect.Type) structMetadata { - packageDir := packageDirOfType(typ) - structName := typ.Name() - if packageDir == "" || structName == "" { - return structMetadata{} - } - - fieldMD := []fieldMetadata{} - for i := 0; i < typ.NumField(); i++ { - f := typ.Field(i) - - if excludedFields[f.Name] { - continue - } - - if f.Anonymous && indirectKind(f.Type) == reflect.Struct { - nestedSM := getStructMetadata(f.Type) - fieldMD = append(fieldMD, nestedSM.Fields...) - continue - // Embedded struct name and doc is irrelevant. - } - - yamlName := getYAMLName(f) - if (yamlName == "" || yamlName == "-" || strings.HasPrefix(yamlName, "_")) && (!isInlinedYAML(f) || indirectKind(f.Type) != reflect.Struct) { - continue - } - - fm := fieldMetadata{ - YAMLName: yamlName, - Doc: structFieldDocs(packageDir, structName)[f.Name], - Default: getDefault(f), - Required: getRequired(f), - Type: indirectKind(f.Type).String(), - } - - if indirectKind(f.Type) == reflect.Struct { - smd := getStructMetadata(indirectType(f.Type)) - fm.ElementStruct = &smd - } else if f.Type.Kind() == reflect.Map || f.Type.Kind() == reflect.Slice { - if f.Type != reflect.TypeOf(yaml.MapSlice(nil)) { - ikind := indirectKind(f.Type.Elem()) - fm.ElementKind = ikind.String() - - if ikind == reflect.Struct { - smd := getStructMetadata(indirectType(f.Type.Elem())) - fm.ElementStruct = &smd - } - } - } - - fieldMD = append(fieldMD, fm) - } - - return structMetadata{ - Name: structName, - Doc: structDoc(packageDir, structName), - Package: packageDir, - Fields: fieldMD, - } -} diff --git a/internal/signalfx-agent/pkg/selfdescribe/types.go b/internal/signalfx-agent/pkg/selfdescribe/types.go deleted file mode 100644 index f906bb3f1d..0000000000 --- a/internal/signalfx-agent/pkg/selfdescribe/types.go +++ /dev/null @@ -1,20 +0,0 @@ -package selfdescribe - -type structMetadata struct { - Name string `json:"name"` - Doc string `json:"doc"` - Package string `json:"package"` - Fields []fieldMetadata `json:"fields"` -} - -type fieldMetadata struct { - YAMLName string `json:"yamlName"` - Doc string `json:"doc"` - Default interface{} `json:"default"` - Required bool `json:"required"` - Type string `json:"type"` - ElementKind string `json:"elementKind"` - // Element is the metadata for the element type of a slice or the value - // type of a map if they are structs. - ElementStruct *structMetadata `json:"elementStruct,omitempty"` -}