crossplane

package module
v0.4.73 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2025 License: Apache-2.0 Imports: 13 Imported by: 3

README

nginx-go-crossplane

A Go port of the NGINX config/JSON converter crossplane.

Parse

This is an example that takes a path to an NGINX config file, converts it to JSON, and prints the result to stdout.

package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/nginxinc/nginx-go-crossplane"
)

func main() {
	path := os.Args[1]

	payload, err := crossplane.Parse(path, &crossplane.ParseOptions{})
	if err != nil {
		panic(err)
	}

	b, err := json.Marshal(payload)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(b))
}

Build

This is an example that takes a path to a JSON file, converts it to an NGINX config, and prints the result to stdout.

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/nginxinc/nginx-go-crossplane"
)

func main() {
	path := os.Args[1]

	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}

	content, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}

	var payload crossplane.Payload
	if err = json.Unmarshal(content, &payload); err != nil {
		panic(err)
	}

	var buf bytes.Buffer
	if err = crossplane.Build(&buf, payload.Config[0], &crossplane.BuildOptions{}); err != nil {
		panic(err)
	}

	fmt.Println(buf.String())
}

Generate support for third-party modules

This is a simple example that takes the path of a third-party module source code to generate support for it. For detailed usage of the tool, please run go run ./cmd/generate/ --help. Assuming the source code path of that module is ./src, you can call go run ./cmd/generate/ --src-path=./src -directive-map-name=directives -match-func-name=Match -match-func-comment=comment. The output will be similar to:

/**
 * Copyright (c) F5, Inc.
 *
 * This source code is licensed under the Apache License, Version 2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

// Code generated by generator; DO NOT EDIT.
// All the definitions are extracted from the source code
// Each bit mask describes these behaviors:
//   - how many arguments the directive can take
//   - whether or not it is a block directive
//   - whether this is a flag (takes one argument that's either "on" or "off")
//   - which contexts it's allowed to be in

package crossplane

var directives = map[string][]uint{
    "my_directive_1": {
        bitmask01|bitmask02|...,
		bitmask11|bitmask12|...,
		...
    },
    "my_directive_2": {
        bitmask01|bitmask02|...,
		bitmask11|bitmask12|...,
		...
    },
}

// comment
func Match(directive string) ([]uint, bool) {
    m, ok := directives[directive]
    return m, ok
}

You can redirect the stdout into a .go file, and pass the generated matchFunc to ParseOptions.DirectiveSources when invoking Parse.

Contributing

If you'd like to contribute to the project, please read our Contributing guide.

License

Apache License, Version 2.0

© F5 Networks, Inc. 2022

Documentation

Index

Constants

View Source
const MaxIndent = 100
View Source
const TokenChanCap = 2048

Variables

View Source
var (
	ErrPrematureLexEnd = errors.New("premature end of file")
)

Functions

func Build

func Build(w io.Writer, config Config, options *BuildOptions) error

Build creates an NGINX config from a crossplane.Config.

func BuildFiles

func BuildFiles(payload Payload, dir string, options *BuildOptions) error

BuildFiles builds all of the config files in a crossplane.Payload and writes them to disk.

func BuildInto

func BuildInto(payload *Payload, into Creator, options *BuildOptions) error

BuildInto builds all of the config files in a crossplane.Payload and writes them to the Creator.

func DefaultDirectivesMatchFunc added in v0.4.45

func DefaultDirectivesMatchFunc(directive string) ([]uint, bool)

func Enquote

func Enquote(arg string) string

func Lex

func Lex(reader io.Reader) chan NgxToken

func LexWithOptions added in v0.4.42

func LexWithOptions(r io.Reader, options LexOptions) chan NgxToken

LexWithOptions allows for custom lexing behavior through external lexers specified in the LexOptions.

func MatchAppProtectWAFv4 added in v0.4.37

func MatchAppProtectWAFv4(directive string) ([]uint, bool)

MatchAppProtectWAFv4 is a MatchFunc for App Protect v4 module.

func MatchAppProtectWAFv5 added in v0.4.37

func MatchAppProtectWAFv5(directive string) ([]uint, bool)

MatchAppProtectWAFv5 is a MatchFunc for App Protect v5 module.

func MatchGeoip2Latest added in v0.4.62

func MatchGeoip2Latest(directive string) ([]uint, bool)

MatchGeoip2Latest is a MatchFunc for the latest version of geoip2.

func MatchHeadersMoreLatest added in v0.4.59

func MatchHeadersMoreLatest(directive string) ([]uint, bool)

MatchHeadersMoreLatest is a MatchFunc for the latest version of headersmore.

func MatchLuaLatest added in v0.4.59

func MatchLuaLatest(directive string) ([]uint, bool)

MatchLuaLatest is a MatchFunc for latest version of Lua.

func MatchNginxPlusLatest added in v0.4.59

func MatchNginxPlusLatest(directive string) ([]uint, bool)

MatchNginxPlusLatest contains directives in latest version of Nginx Plus source code(including GEOIP, Perl, and XSLT)

func MatchNginxPlusR30 added in v0.4.59

func MatchNginxPlusR30(directive string) ([]uint, bool)

func MatchNginxPlusR31 added in v0.4.59

func MatchNginxPlusR31(directive string) ([]uint, bool)

func MatchNginxPlusR33 added in v0.4.72

func MatchNginxPlusR33(directive string) ([]uint, bool)

MatchNginxPlusR33 contains directives in Nginx Plus R33 source code(including GEOIP, Perl, and XSLT)

func MatchNjsLatest added in v0.4.59

func MatchNjsLatest(directive string) ([]uint, bool)

MatchNjsLatest is a MatchFunc for the latest version of njs.

func MatchOss124 added in v0.4.59

func MatchOss124(directive string) ([]uint, bool)

MatchOss124 contains directives in OSS 1.2.4 source code(including GEOIP, Perl, and XSLT)

func MatchOss126 added in v0.4.59

func MatchOss126(directive string) ([]uint, bool)

MatchOss126 contains directives in OSS 1.2.6 source code(including GEOIP, Perl, and XSLT)

func MatchOssLatest added in v0.4.59

func MatchOssLatest(directive string) ([]uint, bool)

MatchOssLatest contains directives in latest version of OSS source code(including GEOIP, Perl, and XSLT)

func MatchOtelLatest added in v0.4.59

func MatchOtelLatest(directive string) ([]uint, bool)

MatchOtelLatest is a MatchFunc for latest version of otel.

func SetTokenChanCap

func SetTokenChanCap(size int)

note: this is only used during tests, should not be changed

Types

type BuildOptions

type BuildOptions struct {
	Indent   int
	Tabs     bool
	Header   bool
	Builders []RegisterBuilder // handle specific directives
	// contains filtered or unexported fields
}

type Builder added in v0.4.42

type Builder interface {
	Build(stmt *Directive) string
}

Builder is the interface implemented by types that can render a Directive as it appears in NGINX configuration files.

Build writes the strings that represent the Directive and it's Block to the io.StringWriter returning any error encountered that caused the write to stop early. Build must not modify the Directive.

type Config

type Config struct {
	File   string        `json:"file"`
	Status string        `json:"status"`
	Errors []ConfigError `json:"errors"`
	Parsed Directives    `json:"parsed"`
}

type ConfigError

type ConfigError struct {
	Line  *int  `json:"line"`
	Error error `json:"error"`
}

type Creator

type Creator interface {
	Create(path string) (io.WriteCloser, error)
	Reset()
}

Creator abstracts file creation (to write configs to something other than files).

type Directive

type Directive struct {
	Directive string     `json:"directive"`
	Line      int        `json:"line"`
	Args      []string   `json:"args"`
	File      string     `json:"file,omitempty"`
	Includes  []int      `json:"includes,omitempty"`
	Block     Directives `json:"block,omitempty"`
	Comment   *string    `json:"comment,omitempty"`
	// IsMapBlockParameter is true if the directive represents a parameter in the body of a "map-like" directive.
	IsMapBlockParameter bool `json:"mapBlockParameter,omitempty"`
}

func (*Directive) Equal

func (d *Directive) Equal(a *Directive) bool

Equal returns true if both blocks are functionally equivalent.

func (Directive) IsBlock

func (d Directive) IsBlock() bool

IsBlock returns true if this is a block directive.

func (Directive) IsComment

func (d Directive) IsComment() bool

IsComment returns true iff the directive represents a comment.

func (Directive) IsInclude

func (d Directive) IsInclude() bool

IsInclude returns true if this is an include directive.

func (*Directive) String

func (d *Directive) String() string

String makes this a Stringer, returning a string representation of the Directive. The string representation is a peak at the content of the Directive, does not represent a valid config rendering of the Directive in question.

type Directives

type Directives []*Directive

type FileString

type FileString struct {
	Name string
	// contains filtered or unexported fields
}

FileString is a string representation of a file.

func (*FileString) Close

func (fs *FileString) Close() error

Close makes this an io.Closer.

func (*FileString) String

func (fs *FileString) String() string

String makes this a Stringer.

func (*FileString) Write

func (fs *FileString) Write(b []byte) (int, error)

Write makes this an io.Writer.

type LexOptions added in v0.4.42

type LexOptions struct {
	Lexers []RegisterLexer
	// contains filtered or unexported fields
}

LexOptions allows customization of the lexing process by specifying external lexers that can handle specific directives. By registering interest in particular directives, external lexers can ensure that these directives are processed separately from the general lexical analysis logic.

type Lexer added in v0.4.42

type Lexer interface {
	// Lex processes a matched token and returns a channel of NgxToken objects.
	// This method performs lexical analysis on the matched token and produces a stream of tokens for the parser to consume.
	// The external lexer should close the channel once it has completed lexing the input to signal the end of tokens.
	// Failure to close the channel will cause the receiver to wait indefinitely.
	Lex(s *SubScanner, matchedToken string) <-chan NgxToken
}

Lexer is an interface for implementing lexers that handle external NGINX tokens during the lexical analysis phase.

type Lua added in v0.4.42

type Lua struct{}

Lua adds support for directives added to NGINX by the ngx_http_lua_module module.

Lua implements the Lexer interface by tokenizing *_by_lua_block directives with a simple Lua parser. The Lua blocks will be placed into a token to be set as an argument on the Lua directive.

Lua also implements the Builder interface by writing the *_by_lua_block directive's contents into the directive's block.

func (*Lua) Build added in v0.4.42

func (l *Lua) Build(stmt *Directive) string

Build generates Lua configurations based on the provided directive.

func (*Lua) Lex added in v0.4.42

func (l *Lua) Lex(s *SubScanner, matchedToken string) <-chan NgxToken

Lex lexically analyzes the Lua blocks based on directives detected. It is used by the lexer to tokenize Lua content within configuration files.

func (*Lua) RegisterBuilder added in v0.4.42

func (l *Lua) RegisterBuilder() RegisterBuilder

RegisterBuilder registers a builder for generating Lua NGINX configuration.

func (*Lua) RegisterLexer added in v0.4.42

func (l *Lua) RegisterLexer() RegisterLexer

RegisterLexer registers a lexer for parsing Lua blocks.

type MatchFunc added in v0.4.37

type MatchFunc func(directive string) (masks []uint, matched bool)

MatchFunc is the signature of the match function used to identify NGINX directives that can be encountered when parsing an NGINX configuration that references dynamic or non-core modules. The argument is the name of a directive found when parsing an NGINX configuration.

The return value is a list of bitmasks that indicate the valid contexts in which the directive may appear as well as the number of arguments the directive accepts. The return value must contain at least one non-zero bitmask if matched is true.

type NgxToken

type NgxToken struct {
	Value    string
	Line     int
	IsQuoted bool
	Error    error
}

type ParseError

type ParseError struct {
	What string
	File *string
	Line *int
	// Raw directive statement causing the parse error.
	Statement string
	// Block in which parse error occurred.
	BlockCtx string
	// contains filtered or unexported fields
}

func (*ParseError) Error

func (e *ParseError) Error() string

func (*ParseError) MarshalJSON

func (e *ParseError) MarshalJSON() ([]byte, error)

func (*ParseError) Unwrap

func (e *ParseError) Unwrap() error

type ParseOptions

type ParseOptions struct {
	// An array of directives to skip over and not include in the payload.
	IgnoreDirectives []string

	// If an error is found while parsing, it will be passed to this callback
	// function. The results of the callback function will be set in the
	// PayloadError struct that's added to the Payload struct's Errors array.
	ErrorCallback func(error) interface{}

	// If specified, use this alternative to open config files
	Open func(path string) (io.ReadCloser, error)

	// Glob will return a matching list of files if specified
	Glob func(path string) ([]string, error)

	// If true, parsing will stop immediately if an error is found.
	StopParsingOnError bool

	// If true, include directives are used to combine all of the Payload's
	// Config structs into one.
	CombineConfigs bool

	// If true, only the config file with the given filename will be parsed
	// and Parse will not parse files included files.
	SingleFile bool

	// If true, comments will be parsed and added to the resulting Payload.
	ParseComments bool

	// If true, add an error to the payload when encountering a directive that
	// is unrecognized. The unrecognized directive will not be included in the
	// resulting Payload.
	ErrorOnUnknownDirectives bool

	// If true, checks that directives are in valid contexts.
	SkipDirectiveContextCheck bool

	// If true, checks that directives have a valid number of arguments.
	SkipDirectiveArgsCheck bool

	// DirectiveSources is used to indicate the set of directives to be expected
	// by the parser. DirectiveSources can include different versions of NGINX
	// and dynamic modules. If DirectiveSources is empty, the parser defaults
	// to DefaultDirectivesMatchFunc.
	DirectiveSources []MatchFunc

	LexOptions LexOptions
}

ParseOptions determine the behavior of an NGINX config parse.

type Payload

type Payload struct {
	Status string         `json:"status"`
	Errors []PayloadError `json:"errors"`
	Config []Config       `json:"config"`
}

func Parse

func Parse(filename string, options *ParseOptions) (*Payload, error)

Parse parses an NGINX configuration file.

func (*Payload) Combined

func (p *Payload) Combined() (*Payload, error)

Combined returns a new Payload that is the same except that the inluding logic is performed on its configs. This means that the resulting Payload will always have 0 or 1 configs in its Config field.

type PayloadError

type PayloadError struct {
	File     string      `json:"file"`
	Line     *int        `json:"line"`
	Error    error       `json:"error"`
	Callback interface{} `json:"callback,omitempty"`
}

type RegisterBuilder added in v0.4.42

type RegisterBuilder interface {
	// contains filtered or unexported methods
}

RegisterBuilder is an option that can be used to add a builder to build NGINX configuration for custom directives.

func BuildWithBuilder added in v0.4.42

func BuildWithBuilder(b Builder, directives ...string) RegisterBuilder

BuildWithBuilder registers a builder to build the NGINX configuration for the given directives.

type RegisterLexer added in v0.4.42

type RegisterLexer interface {
	// contains filtered or unexported methods
}

RegisterLexer is an option that cna be used to add a lexer to tokenize external NGINX tokens.

func LexWithLexer added in v0.4.42

func LexWithLexer(l Lexer, stringTokens ...string) RegisterLexer

LexWithLexer registers a Lexer that implements tokenization of an NGINX configuration after one of the given stringTokens is encountered by Lex.

type StringsCreator

type StringsCreator struct {
	Files []*FileString
}

StringsCreator is an option for rendering config files to strings(s).

func (*StringsCreator) Create

func (sc *StringsCreator) Create(file string) (io.WriteCloser, error)

Create makes this a Creator.

func (*StringsCreator) Reset

func (sc *StringsCreator) Reset()

Reset returns the Creator to its initial state.

type SubScanner added in v0.4.42

type SubScanner struct {
	// contains filtered or unexported fields
}

SubScanner provides an interface for scanning alternative grammars within NGINX configuration data.

func (*SubScanner) Err added in v0.4.42

func (e *SubScanner) Err() error

Err returns the fist non-EOF error encountered by the Scanner.

func (*SubScanner) Line added in v0.4.42

func (e *SubScanner) Line() int

Line returns the line number of the most recent token generated by a call to Scan.

func (*SubScanner) Scan added in v0.4.42

func (e *SubScanner) Scan() bool

Scan advances the scanner to the next token which will be available though the Text method. It returns false when the scan stops by reaching the end of input.

func (*SubScanner) Text added in v0.4.42

func (e *SubScanner) Text() string

Text returns the most recent token generated by a call to Scan.

Directories

Path Synopsis
cmd
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL