Documentation
¶
Overview ¶
Package converter provides functionality to convert device configurations to various formats.
Package converter provides functionality to convert device configurations to markdown.
Package converter provides functionality to convert device configurations to various formats.
Index ¶
- Variables
- func EnrichForExport(data *common.CommonDevice)
- func RenderMarkdown(content string) (string, error)
- func RenderMarkdownToHTML(md string) (string, error)
- func RunConverterTests(t *testing.T, tests []TestCase, ...)
- func RunNewFieldsSerializationTests(t *testing.T)
- func StripMarkdownFormatting(markdown string) (string, error)
- func ValidateMarkdown(content string) error
- type Adapter
- type Converter
- type Format
- type FormatHandler
- type FormatRegistry
- func (r *FormatRegistry) Canonical(format string) (string, bool)
- func (r *FormatRegistry) Extensions() map[string]string
- func (r *FormatRegistry) Get(format string) (FormatHandler, error)
- func (r *FormatRegistry) Register(format string, handler FormatHandler)
- func (r *FormatRegistry) ValidFormats() []string
- func (r *FormatRegistry) ValidFormatsWithAliases() []string
- type Generator
- type HybridGenerator
- func (g *HybridGenerator) Generate(ctx context.Context, data *common.CommonDevice, opts Options) (string, error)
- func (g *HybridGenerator) GenerateToWriter(ctx context.Context, w io.Writer, data *common.CommonDevice, opts Options) error
- func (g *HybridGenerator) GetBuilder() builder.ReportBuilder
- func (g *HybridGenerator) SetBuilder(reportBuilder builder.ReportBuilder)
- type JSONConverter
- type MarkdownConverter
- type Options
- func (o Options) Validate() error
- func (o Options) WithColors(enabled bool) Options
- func (o Options) WithCompact(compact bool) Options
- func (o Options) WithComprehensive(enabled bool) Options
- func (o Options) WithEmojis(enabled bool) Options
- func (o Options) WithFailuresOnly(enabled bool) Options
- func (o Options) WithFormat(format Format) Options
- func (o Options) WithIncludeTunables(enabled bool) Options
- func (o Options) WithMetadata(enabled bool) Options
- func (o Options) WithRedact(redact bool) Options
- func (o Options) WithSections(sections ...string) Options
- func (o Options) WithSuppressWarnings(suppress bool) Options
- func (o Options) WithTables(enabled bool) Options
- func (o Options) WithTheme(theme Theme) Options
- func (o Options) WithWrapWidth(width int) Options
- type StreamingGenerator
- type TestCase
- type Theme
- type YAMLConverter
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnsupportedFormat is returned when an unsupported output format is requested. ErrUnsupportedFormat = errors.New("unsupported format") // ErrNilDevice is returned when the input device configuration is nil. ErrNilDevice = errors.New("device configuration is nil") )
Sentinel errors returned by the converter package.
var DefaultRegistry = newDefaultRegistry() //nolint:gochecknoglobals // package-level singleton
DefaultRegistry is the package-level registry pre-populated with all built-in format handlers. It is the single source of truth for supported formats.
var ErrInvalidWrapWidth = errors.New("wrap width must be -1 (auto-detect), 0 (no wrapping), or positive")
ErrInvalidWrapWidth indicates that the wrap width setting is invalid.
Functions ¶
func EnrichForExport ¶ added in v1.6.0
func EnrichForExport(data *common.CommonDevice)
EnrichForExport populates the read-only enrichment fields on data in place when they are nil: DeviceType (defaulting to OPNsense), Statistics, Analysis, SecurityAssessment, and PerformanceMetrics. ComplianceResults is left alone — it is populated externally by the audit handler.
EnrichForExport is the explicit memoization entry point for callers preparing the same device for multiple format exports (e.g. JSON + YAML + Markdown). analysis.ComputeStatistics and analysis.ComputeAnalysis are linear-or-worse in the number of interfaces, rules, and services and dominate per-format export time; calling EnrichForExport once before the format loop avoids recomputing them per format. Subsequent prepareForExport calls reuse the populated fields and skip the heavy work.
SECURITY: EnrichForExport does not redact sensitive fields. The resulting *CommonDevice carries plaintext secrets — most notably the SNMP community string in Statistics.ServiceDetails — because analysis.ComputeStatistics observes unredacted input by design (presence checks must see real values). Callers MUST NOT marshal or log the device directly after EnrichForExport. Always pass the device through prepareForExport (or a downstream Generator that calls prepareForExport) so the redact branch can produce a clone with the sensitive fields stripped.
Redaction is per-export and is applied by prepareForExport on its shallow copy. The Statistics pointer produced here is reused by every subsequent prepareForExport call — the redact-path clones the Statistics struct before mutating ServiceDetails so a pre-enriched device is safe to share across redact=true and redact=false callers.
CACHE INVALIDATION: EnrichForExport memoizes Statistics and Analysis as a snapshot of the device at call time. If the caller mutates a field that feeds those computations (e.g., device.SNMP.ROCommunity, FirewallRules, Interfaces) after calling EnrichForExport, the cached values go stale and subsequent exports will reflect the pre-mutation state. Re-call EnrichForExport after clearing the affected enrichment field when the underlying configuration changes between exports.
Clearing Statistics is sufficient to invalidate the Statistics-derived fields too: SecurityAssessment and PerformanceMetrics are recomputed together with Statistics. To refresh Analysis, clear Analysis. The two caches are independent.
EnrichForExport is not safe for concurrent use on the same *CommonDevice. Callers preparing one device for parallel format exports must call EnrichForExport once before fanning out.
EnrichForExport on a nil *CommonDevice is a documented no-op. Note that the downstream prepareForExport will still panic on nil; callers must guard nil at their own boundary (the JSONConverter / YAMLConverter wrappers and HybridGenerator.Generate already do).
NOTE: analysis.ComputeStatistics and analysis.ComputeAnalysis intentionally receive the unredacted data so that presence checks (e.g., "is SNMP configured?") see real values.
func RenderMarkdown ¶ added in v1.4.0
RenderMarkdown parses and renders markdown content to HTML using goldmark with extended features (GFM, definition lists, emoji, footnotes). Returns the rendered HTML string or an error if rendering fails. Raw HTML tags (e.g., <details>, <summary>) are preserved in the output.
func RenderMarkdownToHTML ¶ added in v1.3.0
RenderMarkdownToHTML converts markdown content to a self-contained HTML document. It uses goldmark for markdown-to-HTML conversion, transforms GitHub-style alert blockquotes into styled div elements, and wraps the result in htmlShell.
func RunConverterTests ¶
func RunConverterTests( t *testing.T, tests []TestCase, convertFunc func(context.Context, *common.CommonDevice) (string, error), )
RunConverterTests runs the standard converter test suite.
func RunNewFieldsSerializationTests ¶ added in v1.3.0
RunNewFieldsSerializationTests verifies that all new CommonDevice fields appear in both JSON and YAML serialization output and that sensitive data is redacted.
func StripMarkdownFormatting ¶ added in v1.3.0
StripMarkdownFormatting converts markdown to plain text using a goldmark -> HTML -> html2text pipeline. The goldmark renderer (shared with HTML output) handles all markdown parsing, while html2text provides proper HTML-to-text conversion using Go's net/html parser.
Tables and alerts are extracted from the HTML before html2text processing (using placeholders) because html2text doesn't handle table layout or preserve the tab-separated formatting we need.
func ValidateMarkdown ¶ added in v1.4.0
ValidateMarkdown checks if the provided markdown content is syntactically valid. It returns an error if the content cannot be parsed as markdown.
Types ¶
type Adapter ¶
Adapter represents the interface for adapters that bridge between old and new converter implementations.
type Converter ¶
type Converter interface {
ToMarkdown(ctx context.Context, data *common.CommonDevice) (string, error)
}
Converter is the interface for converting device configurations to markdown.
type Format ¶ added in v1.1.0
type Format string
Format represents the output format type.
const ( // FormatMarkdown represents markdown output format. FormatMarkdown Format = "markdown" // FormatJSON represents JSON output format. FormatJSON Format = "json" // FormatYAML represents YAML output format. FormatYAML Format = "yaml" // FormatText represents plain text output format (markdown with formatting stripped). FormatText Format = "text" // FormatHTML represents self-contained HTML output format. FormatHTML Format = "html" )
Supported output format constants for report generation.
type FormatHandler ¶ added in v1.3.0
type FormatHandler interface {
// FileExtension returns the file extension for this format (e.g., ".md", ".json").
FileExtension() string
// Aliases returns alternative names for this format (e.g., "md" for markdown).
Aliases() []string
// Generate creates documentation as a string using the provided generator context.
// The ctx is threaded to per-subsystem boundary checks inside each format's
// generator (e.g., between report body and audit section for markdown).
Generate(ctx context.Context, g *HybridGenerator, data *common.CommonDevice, opts Options) (string, error)
// GenerateToWriter writes documentation directly to the provided io.Writer.
// The ctx is threaded to per-subsystem boundary checks inside each format's
// generator.
GenerateToWriter(
ctx context.Context,
g *HybridGenerator,
w io.Writer,
data *common.CommonDevice,
opts Options,
) error
}
FormatHandler defines the interface for format-specific generation logic. Each handler encapsulates the generation, streaming, and metadata for a single output format, allowing the FormatRegistry to dispatch by format name.
type FormatRegistry ¶ added in v1.3.0
type FormatRegistry struct {
// contains filtered or unexported fields
}
FormatRegistry centralises format dispatch by mapping canonical format names and aliases to FormatHandler implementations. It replaces scattered switch statements with a single source of truth for supported formats.
func NewFormatRegistry ¶ added in v1.3.0
func NewFormatRegistry() *FormatRegistry
NewFormatRegistry creates an empty FormatRegistry.
func (*FormatRegistry) Canonical ¶ added in v1.3.0
func (r *FormatRegistry) Canonical(format string) (string, bool)
Canonical returns the canonical format name for the given format string, resolving aliases. The boolean indicates whether the format was recognized. When ok is false, the returned string is the lowercased input (unresolved).
func (*FormatRegistry) Extensions ¶ added in v1.3.0
func (r *FormatRegistry) Extensions() map[string]string
Extensions returns a map of canonical format name to file extension.
func (*FormatRegistry) Get ¶ added in v1.3.0
func (r *FormatRegistry) Get(format string) (FormatHandler, error)
Get returns the handler for the given format name (canonical or alias). Returns ErrUnsupportedFormat if no handler matches.
func (*FormatRegistry) Register ¶ added in v1.3.0
func (r *FormatRegistry) Register(format string, handler FormatHandler)
Register adds a handler for the given canonical format name. It also registers all aliases returned by handler.Aliases(). Panics on duplicate registration, consistent with the database/sql driver pattern.
func (*FormatRegistry) ValidFormats ¶ added in v1.3.0
func (r *FormatRegistry) ValidFormats() []string
ValidFormats returns a sorted slice of canonical format names.
func (*FormatRegistry) ValidFormatsWithAliases ¶ added in v1.3.0
func (r *FormatRegistry) ValidFormatsWithAliases() []string
ValidFormatsWithAliases returns a sorted slice of all accepted format strings, including both canonical names and aliases.
type Generator ¶ added in v1.1.0
type Generator interface {
// Generate creates documentation in a specified format from the provided device configuration.
// This method returns the complete output as a string, which is useful when the output
// needs further processing (e.g., HTML conversion).
Generate(ctx context.Context, cfg *common.CommonDevice, opts Options) (string, error)
}
Generator interface for creating documentation in various formats.
func NewMarkdownGenerator ¶ added in v1.1.0
NewMarkdownGenerator creates a HybridGenerator configured with a MarkdownBuilder and the provided logger. Despite its name, the returned Generator supports all output formats (Markdown, JSON, YAML, Text, HTML) via the Options passed to Generate(). The opts parameter is ignored and exists for backward compatibility. Returns an error only if the provided logger is nil and creating a default logger fails.
type HybridGenerator ¶ added in v1.1.0
type HybridGenerator struct {
// contains filtered or unexported fields
}
HybridGenerator provides programmatic markdown, JSON, and YAML generation. It uses the builder pattern for markdown output and direct serialization for JSON/YAML.
HybridGenerator implements both Generator (string-based) and StreamingGenerator (io.Writer-based) interfaces. Use GenerateToWriter for memory-efficient streaming output, or Generate when you need the output as a string for further processing.
func NewHybridGenerator ¶ added in v1.1.0
func NewHybridGenerator(reportBuilder builder.ReportBuilder, logger *logging.Logger) (*HybridGenerator, error)
NewHybridGenerator creates a HybridGenerator that uses the provided ReportBuilder and logger. If logger is nil, NewHybridGenerator creates a default logger and returns an error if logger creation fails.
func (*HybridGenerator) Generate ¶ added in v1.1.0
func (g *HybridGenerator) Generate(ctx context.Context, data *common.CommonDevice, opts Options) (string, error)
Generate creates documentation in the specified format from the provided OPNsense configuration. Supported formats: markdown (default), json, yaml, text, and html.
Memory tradeoff (JSON/YAML): Generate pays roughly 2x peak memory for JSON and YAML output because the marshaled byte slice and its string(...) conversion both live on the heap simultaneously. For markdown, text, and HTML the builder already accumulates a string, so there is no additional penalty versus GenerateToWriter. Prefer GenerateToWriter once output approaches ~5MB.
Use Generate when:
- You need the result as an in-memory string (to embed in another structure, pass to a templating system, return from an API handler, or display in a TUI).
- The caller does not have an io.Writer to hand off (no file handle, no http.ResponseWriter, no buffer already in scope).
- Output is small and the ergonomics of a return value matter more than peak memory.
For streaming output, writing directly to a file/socket/HTTP response, or composing with io.Copy / io.MultiWriter, see GenerateToWriter.
func (*HybridGenerator) GenerateToWriter ¶ added in v1.1.0
func (g *HybridGenerator) GenerateToWriter( ctx context.Context, w io.Writer, data *common.CommonDevice, opts Options, ) error
GenerateToWriter writes documentation directly to the provided io.Writer.
Supported formats: markdown (default), json, yaml, text, and html. For markdown, sections are written incrementally as they are generated. For JSON and YAML, an encoder writes directly to w — this avoids the 2x peak-memory hit that Generate incurs (marshaled bytes plus their string(...) conversion both resident at once). For text and HTML, the full output is produced then written because those formats require complete document serialization or post-processing.
Use GenerateToWriter when:
- You are writing directly to a file, socket, or HTTP response.
- Output may be large (>5MB for JSON/YAML) and peak memory matters.
- You want partial-output-on-error semantics: bytes already flushed to w remain visible if encoding fails partway through.
- You are composing with io.Copy, io.MultiWriter, or other writer patterns.
For an in-memory string — for example to embed in another structure, feed a templating system, or return from an API handler — see Generate.
func (*HybridGenerator) GetBuilder ¶ added in v1.1.0
func (g *HybridGenerator) GetBuilder() builder.ReportBuilder
GetBuilder returns the current report builder as a ReportBuilder. The underlying value is typically a ReportBuilder (e.g., *MarkdownBuilder) because SetBuilder and NewHybridGenerator accept ReportBuilder. Returns nil if the builder is nil or does not satisfy the full ReportBuilder interface.
func (*HybridGenerator) SetBuilder ¶ added in v1.1.0
func (g *HybridGenerator) SetBuilder(reportBuilder builder.ReportBuilder)
SetBuilder sets the report builder for programmatic generation.
type JSONConverter ¶
type JSONConverter struct{}
JSONConverter is a JSON converter for device configurations.
func NewJSONConverter ¶
func NewJSONConverter() *JSONConverter
NewJSONConverter creates and returns a new JSONConverter for converting device configurations to JSON format.
func (*JSONConverter) ToJSON ¶
func (c *JSONConverter) ToJSON(_ context.Context, data *common.CommonDevice, redact bool) (string, error)
ToJSON converts a device configuration to JSON. When redact is true, sensitive fields (passwords, private keys, community strings) are replaced with [REDACTED] in the output.
type MarkdownConverter ¶
type MarkdownConverter struct{}
MarkdownConverter is a markdown converter for device configurations.
func NewMarkdownConverter ¶
func NewMarkdownConverter() *MarkdownConverter
NewMarkdownConverter creates and returns a new MarkdownConverter for converting device configuration data to markdown format.
func (*MarkdownConverter) ToMarkdown ¶
func (c *MarkdownConverter) ToMarkdown(_ context.Context, data *common.CommonDevice) (string, error)
ToMarkdown converts a device configuration to markdown.
type Options ¶ added in v1.1.0
type Options struct {
// Format specifies the output format (markdown, json, yaml, text, html).
Format Format
// Comprehensive specifies whether to generate a comprehensive report.
Comprehensive bool
// Sections specifies which configuration sections to include.
Sections []string
// Theme specifies the terminal rendering theme for markdown output.
Theme Theme
// WrapWidth specifies the column width for text wrapping.
WrapWidth int
// EnableTables controls whether to render data as tables.
EnableTables bool
// EnableColors controls whether to use colored output.
EnableColors bool
// EnableEmojis controls whether to include emoji icons in output.
EnableEmojis bool
// Compact controls whether to use a more compact output format.
Compact bool
// IncludeMetadata controls whether to include generation metadata.
IncludeMetadata bool
// SuppressWarnings suppresses non-critical warnings.
SuppressWarnings bool
// IncludeTunables controls whether all system tunables are included in the output.
// When false (default), only security-related tunables are shown in markdown, text, and HTML output.
// JSON and YAML exports always include all tunables regardless of this setting.
IncludeTunables bool
// FailuresOnly filters the plugin control results table to show only non-compliant controls.
// Only meaningful in blue mode audit reports where compliance checks are executed.
FailuresOnly bool
// Redact controls whether sensitive fields (passwords, private keys, community strings, etc.)
// are replaced with [REDACTED] in the output. Defaults to false.
Redact bool
}
Options contains configuration options for report generation.
func DefaultOptions ¶ added in v1.1.0
func DefaultOptions() Options
DefaultOptions returns an Options initialized with the package's default settings for report generation. Defaults: Format=markdown, Theme=auto, WrapWidth=0, EnableTables=true, EnableColors=true, EnableEmojis=true, IncludeMetadata=true, IncludeTunables=false, Comprehensive and Compact set to false, and SuppressWarnings set to false.
func (Options) WithColors ¶ added in v1.1.0
WithColors enables or disables colored output.
func (Options) WithCompact ¶ added in v1.1.0
WithCompact enables or disables compact output format.
func (Options) WithComprehensive ¶ added in v1.1.0
WithComprehensive enables or disables comprehensive report generation.
func (Options) WithEmojis ¶ added in v1.1.0
WithEmojis enables or disables emoji icons.
func (Options) WithFailuresOnly ¶ added in v1.4.0
WithFailuresOnly enables or disables filtering plugin control results to show only failures.
func (Options) WithFormat ¶ added in v1.1.0
WithFormat sets the output format. Format validity is checked by Options.Validate().
func (Options) WithIncludeTunables ¶ added in v1.3.0
WithIncludeTunables enables or disables inclusion of all system tunables. When false, only security-related tunables are shown in reports.
func (Options) WithMetadata ¶ added in v1.1.0
WithMetadata enables or disables generation metadata.
func (Options) WithRedact ¶ added in v1.3.0
WithRedact enables or disables sensitive field redaction.
func (Options) WithSections ¶ added in v1.1.0
WithSections sets the sections to include in output.
func (Options) WithSuppressWarnings ¶ added in v1.1.0
WithSuppressWarnings enables or disables warning suppression.
func (Options) WithTables ¶ added in v1.1.0
WithTables enables or disables table rendering.
func (Options) WithWrapWidth ¶ added in v1.1.0
WithWrapWidth sets the text wrapping width.
type StreamingGenerator ¶ added in v1.1.0
type StreamingGenerator interface {
Generator
// GenerateToWriter writes documentation directly to the provided io.Writer.
// This is more memory-efficient than Generate() for large configurations
// as it streams output section-by-section.
GenerateToWriter(ctx context.Context, w io.Writer, cfg *common.CommonDevice, opts Options) error
}
StreamingGenerator extends Generator with io.Writer-based output support. This interface enables memory-efficient generation by writing directly to the destination without accumulating the entire output in memory first.
type TestCase ¶
type TestCase struct {
Name string
Data *common.CommonDevice
WantErr bool
ErrType error
ValidateOut func(t *testing.T, result string) // Function to validate the output format
}
TestCase represents a test case for converter tests.
func GetCommonTestCases ¶
func GetCommonTestCases() []TestCase
GetCommonTestCases returns common test cases for both JSON and YAML converters.
type Theme ¶ added in v1.1.0
type Theme string
Theme represents the rendering theme for terminal output.
const ( // ThemeAuto automatically detects the appropriate theme. ThemeAuto Theme = "auto" // ThemeDark uses a dark terminal theme. ThemeDark Theme = "dark" // ThemeLight uses a light terminal theme. ThemeLight Theme = "light" // ThemeNone disables styling for plain text output. ThemeNone Theme = "none" )
Supported rendering theme constants for terminal output styling.
type YAMLConverter ¶
type YAMLConverter struct{}
YAMLConverter is a YAML converter for device configurations.
func NewYAMLConverter ¶
func NewYAMLConverter() *YAMLConverter
NewYAMLConverter creates and returns a new YAMLConverter for transforming device configurations to YAML format.
func (*YAMLConverter) ToYAML ¶
func (c *YAMLConverter) ToYAML(_ context.Context, data *common.CommonDevice, redact bool) (string, error)
ToYAML converts a device configuration to YAML. When redact is true, sensitive fields (passwords, private keys, community strings) are replaced with [REDACTED] in the output.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package builder provides programmatic report building functionality for device configurations.
|
Package builder provides programmatic report building functionality for device configurations. |
|
Package formatters provides utility functions for formatting data in markdown reports.
|
Package formatters provides utility functions for formatting data in markdown reports. |