Documentation ¶
Overview ¶
Package yaml contains libraries for manipulating individual Kubernetes Resource Configuration as yaml, keeping yaml structure and comments.
Parsing Resources ¶
Typically Resources will be initialized as collections through the kio package libraries. However it is possible to directly initialize Resources using Parse.
resource, err := yaml.Parse("apiVersion: apps/v1\nkind: Deployment")
Processing Resources ¶
Individual Resources are manipulated using the Pipe and PipeE to apply Filter functions to transform the Resource data.
err := resource.PipeE(yaml.SetAnnotation("key", "value"))
If multiple Filter functions are provided to Pipe or PipeE, each function is applied to the result of the last function -- e.g. yaml.Lookup(...), yaml.SetField(...)
Field values may also be retrieved using Pipe.
annotationValue, err := resource.Pipe(yaml.GetAnnotation("key"))
See http://www.linfo.org/filters.html for a definition of filters.
Common Filters ¶
There are a number of standard filter functions provided by the yaml package.
Working with annotations:
[AnnotationSetter{}, AnnotationGetter{}, AnnotationClearer{}]
Working with fields by path:
[PathMatcher{}, PathGetter{}]
Working with individual fields on Maps and Objects:
[FieldMatcher{}, FieldSetter{}, FieldGetter{}]
Working with individual elements in Sequences:
[ElementAppender{}, ElementSetter{}, ElementMatcher{}]
Writing Filters ¶
Users may implement their own filter functions. When doing so, can be necessary to work with the RNode directly rather than through Pipe. RNode provides a number of functions for doing so. See:
[GetMeta(), Fields(), Elements(), String()]
Example ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: name: app labels: app: java annotations: a.b.c: d.e.f `) if err != nil { log.Fatal(err) } containers, err := Parse(` - name: nginx # first container image: nginx - name: nginx2 # second container image: nginx2 `) if err != nil { log.Fatal(err) } node, err := obj.Pipe( LookupCreate(SequenceNode, "spec", "template", "spec", "containers"), Append(containers.YNode().Content...)) if err != nil { log.Fatal(err) } fmt.Println(node.String()) fmt.Println(obj.String())
Output: <nil> apiVersion: apps/v1 kind: Deployment metadata: name: app labels: app: java annotations: a.b.c: d.e.f spec: template: spec: containers: - name: nginx # first container image: nginx - name: nginx2 # second container image: nginx2 <nil>
Index ¶
- Constants
- Variables
- func DoSerializationHacks(node *yaml.Node)
- func DoSerializationHacksOnNodes(nodes []*RNode)
- func ErrorIfAnyInvalidAndNonNull(kind yaml.Kind, rn ...*RNode) error
- func ErrorIfInvalid(rn *RNode, kind yaml.Kind) error
- func FormatNonStringStyle(node *Node, schema spec.Schema)
- func GetValue(node *RNode) string
- func IncrementFieldIndex(i int) int
- func IsCreate(kind yaml.Kind) bool
- func IsEmpty(node *RNode) bool
- func IsFieldEmpty(node *MapNode) bool
- func IsFieldNull(node *MapNode) bool
- func IsFoundOrError(rn *RNode, err error) bool
- func IsListIndex(p string) bool
- func IsMissingOrError(rn *RNode, err error) bool
- func IsMissingOrNull(node *RNode) bool
- func IsNull(node *RNode) bool
- func IsValueNonString(value string) bool
- func IsYaml1_1NonString(node *Node) bool
- func SplitIndexNameValue(p string) (string, string, error)
- func String(node *yaml.Node, opts ...string) (string, error)
- func UndoSerializationHacks(node *yaml.Node)
- func UndoSerializationHacksOnNodes(nodes []*RNode)
- func UpdateFile(filter Filter, path string) error
- func WriteFile(node *RNode, path string) error
- type AnnotationClearer
- type AnnotationGetter
- type AnnotationSetter
- type Decoder
- type ElementAppender
- type ElementMatcher
- type ElementSetter
- type Encoder
- type FieldClearer
- type FieldMatcher
- type FieldSetter
- type Filter
- type FilterFunc
- type FilterMatcher
- type IsZeroer
- type Kind
- type LabelSetter
- type MapNode
- type MapNodeSlice
- type Marshaler
- type Node
- type ObjectMeta
- type Parser
- type PathGetter
- type PathMatcher
- type PrefixSetter
- type RNode
- func ConvertJSONToYamlNode(jsonStr string) (*RNode, error)
- func MustParse(value string) *RNode
- func NewListRNode(values ...string) *RNode
- func NewRNode(value *yaml.Node) *RNode
- func NewScalarRNode(value string) *RNode
- func NullNode() *RNode
- func Parse(value string) (*RNode, error)
- func ReadFile(path string) (*RNode, error)
- func (rn *RNode) AppendToFieldPath(parts ...string)
- func (rn *RNode) Content() []*yaml.Node
- func (rn *RNode) Document() *yaml.Node
- func (rn *RNode) Element(key, value string) *RNode
- func (rn *RNode) ElementValues(key string) ([]string, error)
- func (rn *RNode) Elements() ([]*RNode, error)
- func (rn *RNode) Field(field string) *MapNode
- func (rn *RNode) FieldPath() []string
- func (rn *RNode) Fields() ([]string, error)
- func (rn *RNode) GetAssociativeKey() string
- func (rn *RNode) GetMeta() (ResourceMeta, error)
- func (rn *RNode) IsAssociative() bool
- func (rn *RNode) MarshalJSON() ([]byte, error)
- func (rn *RNode) MustString() string
- func (rn *RNode) Pipe(functions ...Filter) (*RNode, error)
- func (rn *RNode) PipeE(functions ...Filter) error
- func (rn *RNode) SetYNode(node *yaml.Node)
- func (rn *RNode) String() (string, error)
- func (rn *RNode) UnmarshalJSON(b []byte) error
- func (rn *RNode) VisitElements(fn func(node *RNode) error) error
- func (rn *RNode) VisitFields(fn func(node *MapNode) error) error
- func (rn *RNode) YNode() *yaml.Node
- type ResourceIdentifier
- type ResourceMeta
- type Style
- type SuffixSetter
- type TeePiper
- type TypeError
- type TypeMeta
- type Unmarshaler
- type ValueReplacer
- type YFilter
- type YFilters
Examples ¶
- Package
- Append (AppendMap)
- Append (AppendScalars)
- Clear
- ElementMatcher.Filter
- ElementMatcher.Filter (ObjectFound)
- ElementMatcher.Filter (ObjectNotFound)
- ElementMatcher.Filter (PrimitiveFound)
- FieldMatcher.Filter
- Get
- Get (NotFound)
- Lookup (Element)
- Lookup (NotFound)
- Lookup (Scalar)
- Lookup (Sequence)
- LookupCreate (Element)
- LookupCreate (Object)
- LookupCreate (Sequence)
- PathGetter.Filter
- RNode.ElementValues
- RNode.Elements
- SetField
- SetField (StringValue)
- SetField (StringValueOverwrite)
- Tee
Constants ¶
const ( AnnotationsField = "annotations" APIVersionField = "apiVersion" KindField = "kind" MetadataField = "metadata" NameField = "name" NamespaceField = "namespace" LabelsField = "labels" )
Field names
const ( Trim = "Trim" Flow = "Flow" )
const ( StringTag = "!!str" BoolTag = "!!bool" IntTag = "!!int" )
const ( // NullNodeTag is the tag set for a yaml.Document that contains no data -- e.g. it isn't a // Map, Slice, Document, etc NullNodeTag = "!!null" )
Variables ¶
var AliasNode yaml.Kind = yaml.AliasNode
var AssociativeSequenceKeys = []string{"name"}
AssociativeSequenceKeys is a map of paths to sequences that have associative keys. The order sets the precedence of the merge keys -- if multiple keys are present in Resources in a list, then the FIRST key which ALL elements in the list have is used as the associative key for merging that list. Only infer name as a merge key.
var DocumentNode yaml.Kind = yaml.DocumentNode
var DoubleQuotedStyle yaml.Style = yaml.DoubleQuotedStyle
var ErrMissingMetadata = fmt.Errorf("missing Resource metadata")
var FieldOrder = func() map[string]int { fo := map[string]int{} for i, f := range fieldSortOrder { fo[f] = i + 1 } return fo }()
FieldOrder indexes fields and maps them to relative precedence
var Filters = map[string]func() Filter{ "AnnotationClearer": func() Filter { return &AnnotationClearer{} }, "AnnotationGetter": func() Filter { return &AnnotationGetter{} }, "AnnotationSetter": func() Filter { return &AnnotationSetter{} }, "LabelSetter": func() Filter { return &LabelSetter{} }, "ElementAppender": func() Filter { return &ElementAppender{} }, "ElementMatcher": func() Filter { return &ElementMatcher{} }, "FieldClearer": func() Filter { return &FieldClearer{} }, "FilterMatcher": func() Filter { return &FilterMatcher{} }, "FieldMatcher": func() Filter { return &FieldMatcher{} }, "FieldSetter": func() Filter { return &FieldSetter{} }, "PathGetter": func() Filter { return &PathGetter{} }, "PathMatcher": func() Filter { return &PathMatcher{} }, "Parser": func() Filter { return &Parser{} }, "PrefixSetter": func() Filter { return &PrefixSetter{} }, "ValueReplacer": func() Filter { return &ValueReplacer{} }, "SuffixSetter": func() Filter { return &SuffixSetter{} }, "TeePiper": func() Filter { return &TeePiper{} }, }
Filters is the list of serializable Pipeline Filters
var FlowStyle yaml.Style = yaml.FlowStyle
var FoldedStyle yaml.Style = yaml.FoldedStyle
var LiteralStyle yaml.Style = yaml.LiteralStyle
var MappingNode yaml.Kind = yaml.MappingNode
var Marshal = yaml.Marshal
var NewDecoder = yaml.NewDecoder
var NewEncoder = func(w io.Writer) *yaml.Encoder {
e := yaml.NewEncoder(w)
e.SetIndent(2)
return e
}
var ScalarNode yaml.Kind = yaml.ScalarNode
var SequenceNode yaml.Kind = yaml.SequenceNode
var SingleQuotedStyle yaml.Style = yaml.SingleQuotedStyle
var TaggedStyle yaml.Style = yaml.TaggedStyle
var Unmarshal = yaml.Unmarshal
var WhitelistedListSortApis = newSet(
"apps/v1", "apps/v1beta1", "apps/v1beta2", "batch/v1", "batch/v1beta1",
"extensions/v1beta1", "v1", "admissionregistration.k8s.io/v1beta1")
WhitelistedListSortApis contains the set of apis that are whitelisted for sorting list field elements
var WhitelistedListSortFields = map[string]string{
".spec.template.spec.containers": "name",
".webhooks.rules.operations": "",
}
WhitelistedListSortFields contains json paths to list fields that should be sorted, and the field they should be sorted by
var WhitelistedListSortKinds = newSet(
"CronJob", "DaemonSet", "Deployment", "Job", "ReplicaSet", "StatefulSet",
"ValidatingWebhookConfiguration")
WhitelistedListSortKinds contains the set of kinds that are whitelisted for sorting list field elements
Functions ¶
func DoSerializationHacks ¶ added in v0.1.4
func DoSerializationHacks(node *yaml.Node)
DoSerializationHacks addresses a bug in yaml V3 upstream, it parses the yaml node, and rearranges the head comments of the children of sequence node. Refer to https://github.com/go-yaml/yaml/issues/587 for more details
func DoSerializationHacksOnNodes ¶ added in v0.1.4
func DoSerializationHacksOnNodes(nodes []*RNode)
func ErrorIfInvalid ¶
func FormatNonStringStyle ¶ added in v0.0.6
FormatNonStringStyle makes sure that values which parse as non-string values in yaml 1.1 are correctly formatted given the Schema type.
func IncrementFieldIndex ¶
IncrementFieldIndex increments i to point to the next field name element in a slice of Contents.
func IsEmpty ¶
IsEmpty returns true if the RNode is MissingOrNull, or is either a MappingNode with no fields, or a SequenceNode with no elements.
func IsFieldEmpty ¶
func IsFieldNull ¶
func IsFoundOrError ¶
IsFoundOrError returns true if rn is found or err is non-nil
func IsListIndex ¶
IsListIndex returns true if p is an index into a Val. e.g. [fieldName=fieldValue] e.g. [=primitiveValue]
func IsMissingOrError ¶
IsMissingOrError returns true if rn is NOT found or err is non-nil
func IsMissingOrNull ¶
IsMissingOrNull returns true if the RNode is nil or contains and explicitly null value.
func IsValueNonString ¶ added in v0.1.11
func IsYaml1_1NonString ¶ added in v0.0.6
IsYaml1_1NonString returns true if the value parses as a non-string value in yaml 1.1 when unquoted.
Note: yaml 1.2 uses different keywords than yaml 1.1. Example: yaml 1.2 interprets `field: on` and `field: "on"` as equivalent (both strings). However Yaml 1.1 interprets `field: on` as on being a bool and `field: "on"` as on being a string. If an input is read with `field: "on"`, and the style is changed from DoubleQuote to 0, it will change the type of the field from a string to a bool. For this reason, fields which are keywords in yaml 1.1 should never have their style changed, as it would break backwards compatibility with yaml 1.1 -- which is what is used by the Kubernetes apiserver.
func SplitIndexNameValue ¶
SplitIndexNameValue splits a lookup part Val index into the field name and field value to match. e.g. splits [name=nginx] into (name, nginx) e.g. splits [=-jar] into ("", jar)
func UndoSerializationHacks ¶ added in v0.1.4
func UndoSerializationHacks(node *yaml.Node)
UndoSerializationHacks reverts the changes made by DoSerializationHacks Refer to https://github.com/go-yaml/yaml/issues/587 for more details
func UndoSerializationHacksOnNodes ¶ added in v0.1.4
func UndoSerializationHacksOnNodes(nodes []*RNode)
func UpdateFile ¶ added in v0.0.12
UpdateFile reads the file at path, applies the filter to it, and write the result back. path must contain a exactly 1 resource (YAML).
Types ¶
type AnnotationClearer ¶
type AnnotationClearer struct { Kind string `yaml:"kind,omitempty"` Key string `yaml:"key,omitempty"` }
AnnotationClearer removes an annotation at metadata.annotations. Returns nil if the annotation or field does not exist.
func ClearAnnotation ¶
func ClearAnnotation(key string) AnnotationClearer
type AnnotationGetter ¶
type AnnotationGetter struct { Kind string `yaml:"kind,omitempty"` Key string `yaml:"key,omitempty"` Value string `yaml:"value,omitempty"` }
AnnotationGetter gets an annotation at metadata.annotations. Returns nil if metadata.annotations does not exist.
func GetAnnotation ¶
func GetAnnotation(key string) AnnotationGetter
type AnnotationSetter ¶
type AnnotationSetter struct { Kind string `yaml:"kind,omitempty"` Key string `yaml:"key,omitempty"` Value string `yaml:"value,omitempty"` }
AnnotationSetter sets an annotation at metadata.annotations. Creates metadata.annotations if does not exist.
func SetAnnotation ¶
func SetAnnotation(key, value string) AnnotationSetter
type ElementAppender ¶
type ElementAppender struct { Kind string `yaml:"kind,omitempty"` // Elem is the value to append. Elements []*yaml.Node `yaml:"elements,omitempty"` }
ElementAppender adds all element to a SequenceNode's Content. Returns Elements[0] if len(Elements) == 1, otherwise returns nil.
func Append ¶
func Append(elements ...*yaml.Node) ElementAppender
Append creates an ElementAppender
Example (AppendMap) ¶
obj, err := Parse(` - name: foo - name: bar `) if err != nil { log.Fatal(err) } elem, err := Parse("name: baz") if err != nil { log.Fatal(err) } node, err := obj.Pipe(Append(elem.YNode())) if err != nil { log.Fatal(err) } // Expect the node to contain the appended element because only // 1 element was appended fmt.Println(node.String()) fmt.Println(obj.String())
Output: name: baz <nil> - name: foo - name: bar - name: baz <nil>
Example (AppendScalars) ¶
obj, err := Parse(` - a - b `) if err != nil { log.Fatal(err) } _, err = obj.Pipe(Append(&Node{Value: "c", Kind: ScalarNode})) if err != nil { log.Fatal(err) } node, err := obj.Pipe(Append( &Node{Value: "c", Kind: ScalarNode}, &Node{Value: "d", Kind: ScalarNode}, )) if err != nil { log.Fatal(err) } fmt.Println(node.String()) fmt.Println(obj.String())
Output: <nil> - a - b - c - c - d <nil>
type ElementMatcher ¶
type ElementMatcher struct { Kind string `yaml:"kind,omitempty"` // FieldName will attempt to match this field in each list element. // Optional. Leave empty for lists of primitives (ScalarNode). FieldName string `yaml:"name,omitempty"` // FieldValue will attempt to match each element field to this value. // For lists of primitives, this will be used to match the primitive value. FieldValue string `yaml:"value,omitempty"` // Create will create the Element if it is not found Create *RNode `yaml:"create,omitempty"` }
ElementMatcher returns the first element from a Sequence matching the specified field's value.
func MatchElement ¶
func MatchElement(field, value string) ElementMatcher
func (ElementMatcher) Filter ¶
func (e ElementMatcher) Filter(rn *RNode) (*RNode, error)
Example ¶
obj, err := Parse(` - a - b `) if err != nil { log.Fatal(err) } elem, err := obj.Pipe(ElementMatcher{ FieldValue: "c", Create: NewScalarRNode("c"), }) if err != nil { log.Fatal(err) } fmt.Println(elem.String()) fmt.Println(obj.String())
Output: c <nil> - a - b - c <nil>
Example (ObjectFound) ¶
obj, err := Parse(` - name: foo - name: bar - name: baz `) if err != nil { log.Fatal(err) } append, err := Parse(` name: baz image: nginx `) if err != nil { log.Fatal(err) } elem, err := obj.Pipe(ElementMatcher{ FieldName: "name", FieldValue: "baz", Create: append}) if err != nil { log.Fatal(err) } fmt.Println(elem.String()) fmt.Println(obj.String())
Output: name: baz <nil> - name: foo - name: bar - name: baz <nil>
Example (ObjectNotFound) ¶
obj, err := Parse(` - name: foo - name: bar `) if err != nil { log.Fatal(err) } append, err := Parse(` name: baz image: nginx `) if err != nil { log.Fatal(err) } elem, err := obj.Pipe(ElementMatcher{ FieldName: "name", FieldValue: "baz", Create: append}) if err != nil { log.Fatal(err) } fmt.Println(elem.String()) fmt.Println(obj.String())
Output: name: baz image: nginx <nil> - name: foo - name: bar - name: baz image: nginx <nil>
Example (PrimitiveFound) ¶
obj, err := Parse(` - a - b - c `) if err != nil { log.Fatal(err) } elem, err := obj.Pipe(ElementMatcher{ FieldValue: "c", Create: NewScalarRNode("c"), }) if err != nil { log.Fatal(err) } fmt.Println(elem.String()) fmt.Println(obj.String())
Output: c <nil> - a - b - c <nil>
type ElementSetter ¶
type ElementSetter struct { Kind string `yaml:"kind,omitempty"` // Element is the new value to set -- remove the existing element if nil Element *Node // Key is a field on the elements. It is used to find the matching element to // update / delete. Key string `yaml:"key,omitempty"` // Value is a field value on the elements. It is used to find matching elements to // update / delete. Value string `yaml:"value,omitempty"` }
ElementSetter sets the value for an Element in an associative list. ElementSetter will remove any elements which are empty.
type FieldClearer ¶
type FieldClearer struct { Kind string `yaml:"kind,omitempty"` // Name is the name of the field or key in the map. Name string `yaml:"name,omitempty"` IfEmpty bool `yaml:"ifEmpty,omitempty"` }
FieldClearer removes the field or map key. Returns a RNode with the removed field or map entry.
func Clear ¶
func Clear(name string) FieldClearer
Clear returns a FieldClearer
Example ¶
obj, err := Parse(` kind: Deployment metadata: name: app annotations: a.b.c: d.e.f g: h spec: template: {} `) if err != nil { log.Fatal(err) } node, err := obj.Pipe(Clear("metadata")) if err != nil { log.Fatal(err) } fmt.Println(node.String()) fmt.Println(obj.String())
Output: name: app annotations: a.b.c: d.e.f g: h <nil> kind: Deployment spec: template: {} <nil>
type FieldMatcher ¶
type FieldMatcher struct { Kind string `yaml:"kind,omitempty"` // Name of the field to return Name string `yaml:"name,omitempty"` // YNode of the field to return. // Optional. Will only need to match field name if unset. Value *RNode `yaml:"value,omitempty"` StringValue string `yaml:"stringValue,omitempty"` StringRegexValue string `yaml:"stringRegexValue,omitempty"` // Create will cause the field to be created with this value // if it is set. Create *RNode `yaml:"create,omitempty"` }
FieldMatcher returns the value of a named field or map entry.
func Get ¶
func Get(name string) FieldMatcher
Example ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: name: app annotations: a.b.c: d.e.f g: h spec: template: {} `) if err != nil { log.Fatal(err) } node, err := obj.Pipe(Get("metadata")) if err != nil { log.Fatal(err) } fmt.Println(node.String()) fmt.Println(obj.String())
Output: name: app annotations: a.b.c: d.e.f g: h <nil> apiVersion: apps/v1 kind: Deployment metadata: name: app annotations: a.b.c: d.e.f g: h spec: template: {} <nil>
Example (NotFound) ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment spec: template: {} `) if err != nil { log.Fatal(err) } node, err := obj.Pipe(FieldMatcher{Name: "metadata"}) if err != nil { log.Fatal(err) } fmt.Println(node.String()) fmt.Println(obj.String())
Output: <nil> apiVersion: apps/v1 kind: Deployment spec: template: {} <nil>
func Match ¶
func Match(value string) FieldMatcher
func MatchField ¶
func MatchField(name, value string) FieldMatcher
func (FieldMatcher) Filter ¶
func (f FieldMatcher) Filter(rn *RNode) (*RNode, error)
Example ¶
obj, err := Parse(` kind: Deployment spec: template: {} `) if err != nil { log.Fatal(err) } value, err := Parse(` name: app annotations: a.b.c: d.e.f g: h `) if err != nil { log.Fatal(err) } elem, err := obj.Pipe(FieldMatcher{ Name: "metadata", Value: value, Create: value}) if err != nil { log.Fatal(err) } fmt.Println(elem.String()) fmt.Println(obj.String())
Output: name: app annotations: a.b.c: d.e.f g: h <nil> kind: Deployment spec: template: {} metadata: name: app annotations: a.b.c: d.e.f g: h <nil>
type FieldSetter ¶
type FieldSetter struct { Kind string `yaml:"kind,omitempty"` // Name is the name of the field or key to lookup in a MappingNode. // If Name is unspecified, and the input is a ScalarNode, FieldSetter will set the // value on the ScalarNode. Name string `yaml:"name,omitempty"` // Value is the value to set. // Optional if Kind is set. Value *RNode `yaml:"value,omitempty"` StringValue string `yaml:"stringValue,omitempty"` // OverrideStyle can be set to override the style of the existing node // when setting it. Otherwise, if an existing node is found, the style is // retained. OverrideStyle bool `yaml:"overrideStyle,omitempty"` }
FieldSetter sets a field or map entry to a value.
func Set ¶
func Set(value *RNode) FieldSetter
func SetField ¶
func SetField(name string, value *RNode) FieldSetter
Example ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: name: app labels: app: java annotations: a.b.c: d.e.f `) if err != nil { log.Fatal(err) } containers, err := Parse(` - name: nginx # first container image: nginx - name: nginx2 # second container image: nginx2 `) if err != nil { log.Fatal(err) } _, err = obj.Pipe( LookupCreate(MappingNode, "spec", "template", "spec"), SetField("containers", containers)) if err != nil { log.Fatal(err) } fmt.Println(obj.String())
Output: apiVersion: apps/v1 kind: Deployment metadata: name: app labels: app: java annotations: a.b.c: d.e.f spec: template: spec: containers: - name: nginx # first container image: nginx - name: nginx2 # second container image: nginx2 <nil>
Example (StringValue) ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: name: app `) if err != nil { log.Fatal(err) } _, err = obj.Pipe(SetField("foo", NewScalarRNode("bar"))) if err != nil { log.Fatal(err) } fmt.Println(obj.String())
Output: apiVersion: apps/v1 kind: Deployment metadata: name: app foo: bar <nil>
Example (StringValueOverwrite) ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: name: app foo: baz `) if err != nil { // handle error } // set metadata.annotations.foo = bar _, err = obj.Pipe(SetField("foo", NewScalarRNode("bar"))) if err != nil { // handle error } fmt.Println(obj.String())
Output: apiVersion: apps/v1 kind: Deployment metadata: name: app foo: bar <nil>
type Filter ¶
Filter defines a function to manipulate an individual RNode such as by changing its values, or returning a field.
When possible, Filters should be serializable to yaml so that they can be described declaratively as data.
Analogous to http://www.linfo.org/filters.html
func Tee ¶
Tee calls the provided Filters, and returns its argument rather than the result of the filters. May be used to fork sub-filters from a call. e.g. locate field, set value; locate another field, set another value
Example ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 `) if err != nil { // handle error } // set metadata.annotations.foo = bar _, err = obj.Pipe( Lookup("spec", "template", "spec", "containers", "[name=nginx]"), Tee(SetField("filter", NewListRNode("foo"))), SetField("args", NewListRNode("baz", "bar"))) if err != nil { // handle error } fmt.Println(obj.String())
Output: apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 filter: - foo args: - baz - bar <nil>
type FilterFunc ¶
type FilterMatcher ¶
type LabelSetter ¶ added in v0.1.1
type LabelSetter struct { Kind string `yaml:"kind,omitempty"` Key string `yaml:"key,omitempty"` Value string `yaml:"value,omitempty"` }
LabelSetter sets a label at metadata.labels. Creates metadata.labels if does not exist.
func SetLabel ¶ added in v0.1.1
func SetLabel(key, value string) LabelSetter
type MapNodeSlice ¶
type MapNodeSlice []*MapNode
func (MapNodeSlice) Keys ¶
func (m MapNodeSlice) Keys() []*RNode
func (MapNodeSlice) Values ¶
func (m MapNodeSlice) Values() []*RNode
type ObjectMeta ¶
type ObjectMeta struct { // Name is the metadata.name field of a Resource Name string `yaml:"name,omitempty"` // Namespace is the metadata.namespace field of a Resource Namespace string `yaml:"namespace,omitempty"` // Labels is the metadata.labels field of a Resource Labels map[string]string `yaml:"labels,omitempty"` // Annotations is the metadata.annotations field of a Resource. Annotations map[string]string `yaml:"annotations,omitempty"` }
ObjectMeta contains metadata about a Resource
type PathGetter ¶
type PathGetter struct { Kind string `yaml:"kind,omitempty"` // Path is a slice of parts leading to the RNode to lookup. // Each path part may be one of: // * FieldMatcher -- e.g. "spec" // * Map Key -- e.g. "app.k8s.io/version" // * List Entry -- e.g. "[name=nginx]" or "[=-jar]" // // Map Keys and Fields are equivalent. // See FieldMatcher for more on Fields and Map Keys. // // List Entries are specified as map entry to match [fieldName=fieldValue]. // See Elem for more on List Entries. // // Examples: // * spec.template.spec.container with matching name: [name=nginx] // * spec.template.spec.container.argument matching a value: [=-jar] Path []string `yaml:"path,omitempty"` // Create will cause missing path parts to be created as they are walked. // // * The leaf Node (final path) will be created with a Kind matching Create // * Intermediary Nodes will be created as either a MappingNodes or // SequenceNodes as appropriate for each's Path location. Create yaml.Kind `yaml:"create,omitempty"` // Style is the style to apply to created value Nodes. // Created key Nodes keep an unspecified Style. Style yaml.Style `yaml:"style,omitempty"` }
PathGetter returns the RNode under Path.
func Lookup ¶
func Lookup(path ...string) PathGetter
Lookup returns a PathGetter to lookup a field by its path.
Example (Element) ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: containers: - name: nginx image: nginx:latest `) if err != nil { log.Fatal(err) } value, err := obj.Pipe(Lookup( "spec", "templates", "spec", "containers", "[name=nginx]")) if err != nil { log.Fatal(err) } fmt.Println(value.String())
Output: name: nginx image: nginx:latest <nil>
Example (NotFound) ¶
obj, err := Parse(` kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app `) if err != nil { log.Fatal(err) } rs, err := obj.Pipe(Lookup("spec", "templates", "spec")) if err != nil { log.Fatal(err) } fmt.Println(rs) fmt.Println("---") fmt.Println(obj.String())
Output: <nil> --- kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app <nil>
Example (Scalar) ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: containers: - name: nginx image: nginx:latest `) if err != nil { log.Fatal(err) } value, err := obj.Pipe(Lookup( "spec", "templates", "spec", "containers", "[name=nginx]", "image")) if err != nil { log.Fatal(err) } fmt.Println(value.String())
Output: nginx:latest <nil>
Example (Sequence) ¶
obj, err := Parse(`apiVersion: apps/v1 kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: containers: - name: nginx image: nginx:latest `) if err != nil { log.Fatal(err) } value, err := obj.Pipe(Lookup( "spec", "templates", "spec", "containers")) if err != nil { log.Fatal(err) } fmt.Println(value.String())
Output: - name: nginx image: nginx:latest <nil>
func LookupCreate ¶
func LookupCreate(kind yaml.Kind, path ...string) PathGetter
Lookup returns a PathGetter to lookup a field by its path and create it if it doesn't already exist.
Example (Element) ¶
obj, err := Parse(` kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app `) if err != nil { log.Fatal(err) } rs, err := obj.Pipe(LookupCreate( MappingNode, "spec", "templates", "spec", "containers", "[name=nginx]")) if err != nil { log.Fatal(err) } fmt.Println(rs.String()) fmt.Println("---") fmt.Println(obj.String())
Output: name: nginx <nil> --- kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: containers: - name: nginx <nil>
Example (Object) ¶
obj, err := Parse(` kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app `) if err != nil { log.Fatal(err) } rs, err := obj.Pipe(LookupCreate( MappingNode, "spec", "templates", "spec")) if err != nil { log.Fatal(err) } fmt.Println(rs.String()) fmt.Println("---") fmt.Println(obj.String())
Output: {} <nil> --- kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: {} <nil>
Example (Sequence) ¶
obj, err := Parse(` kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app `) if err != nil { log.Fatal(err) } rs, err := obj.Pipe(LookupCreate( SequenceNode, "spec", "templates", "spec", "containers")) if err != nil { log.Fatal(err) } fmt.Println(rs.String()) fmt.Println("---") fmt.Println(obj.String())
Output: [] <nil> --- kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: containers: [] <nil>
func (PathGetter) Filter ¶
func (l PathGetter) Filter(rn *RNode) (*RNode, error)
Example ¶
obj, err := Parse(` kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app `) if err != nil { log.Fatal(err) } rs, err := obj.Pipe(PathGetter{ Path: []string{"spec", "templates", "spec", "containers", "[name=nginx]", "image"}, Create: ScalarNode, }) if err != nil { log.Fatal(err) } rs.Document().Style = SingleQuotedStyle fmt.Println(rs.String()) fmt.Println("---") fmt.Println(obj.String())
Output: '' <nil> --- kind: Deployment metadata: labels: app: java annotations: a.b.c: d.e.f name: app spec: templates: spec: containers: - name: nginx image: '' <nil>
type PathMatcher ¶
type PathMatcher struct { Kind string `yaml:"kind,omitempty"` // Path is a slice of parts leading to the RNode to lookup. // Each path part may be one of: // * FieldMatcher -- e.g. "spec" // * Map Key -- e.g. "app.k8s.io/version" // * List Entry -- e.g. "[name=nginx]" or "[=-jar]" // // Map Keys and Fields are equivalent. // See FieldMatcher for more on Fields and Map Keys. // // List Entries are specified as map entry to match [fieldName=fieldValue]. // See Elem for more on List Entries. // // Examples: // * spec.template.spec.container with matching name: [name=nginx] -- match 'name': 'nginx' // * spec.template.spec.container.argument matching a value: [=-jar] -- match '-jar' Path []string `yaml:"path,omitempty"` // Matches is set by PathMatch to publish the matched element values for each node. // After running PathMatcher.Filter, each node from the SequenceNode result may be // looked up in Matches to find the field values that were matched. Matches map[*Node][]string // StripComments may be set to remove the comments on the matching Nodes. // This is useful for if the nodes are to be printed in FlowStyle. StripComments bool // contains filtered or unexported fields }
PathMatcher returns all RNodes matching the path wrapped in a SequenceNode. Lists may have multiple elements matching the path, and each matching element is added to the return result. If Path points to a SequenceNode, the SequenceNode is wrapped in another SequenceNode If Path does not contain any lists, the result is still wrapped in a SequenceNode of len == 1
type PrefixSetter ¶
type RNode ¶
type RNode struct { Match []string // contains filtered or unexported fields }
RNode provides functions for manipulating Kubernetes Resources Objects unmarshalled into *yaml.Nodes
func ConvertJSONToYamlNode ¶ added in v0.1.12
ConvertJSONToYamlNode parses input json string and returns equivalent yaml node
func NewListRNode ¶
NewListRNode returns a new List *RNode containing the provided scalar values.
func NewRNode ¶
func NewRNode(value *yaml.Node) *RNode
NewRNode returns a new RNode pointer containing the provided Node.
func NewScalarRNode ¶
NewScalarRNode returns a new Scalar *RNode containing the provided scalar value.
func (*RNode) AppendToFieldPath ¶
AppendToFieldPath appends a field name to the FieldPath.
func (*RNode) Document ¶
func (rn *RNode) Document() *yaml.Node
Document returns the Node RNode for the value. Does not unwrap the node if it is a DocumentNodes
func (*RNode) Element ¶
Element returns the element in the list which contains the field matching the value. Returns nil for non-SequenceNodes or if no Element matches.
func (*RNode) ElementValues ¶
ElementValues returns a list of all observed values for a given field name in a list of elements. Returns error for non-SequenceNodes.
Example ¶
resource, err := Parse(` - name: foo args: ['run.sh'] - name: bar args: ['run.sh'] - name: baz args: ['run.sh'] `) if err != nil { log.Fatal(err) } fmt.Println(resource.ElementValues("name"))
Output: [foo bar baz] <nil>
func (*RNode) Elements ¶
Elements returns the list of elements in the RNode. Returns an error for non-SequenceNodes.
Example ¶
resource, err := Parse(` - name: foo args: ['run.sh'] - name: bar args: ['run.sh'] - name: baz args: ['run.sh'] `) if err != nil { log.Fatal(err) } elements, err := resource.Elements() if err != nil { log.Fatal(err) } for i, e := range elements { fmt.Printf("Element: %d\n", i) fmt.Println(e.MustString()) }
Output: Element: 0 name: foo args: ['run.sh'] Element: 1 name: bar args: ['run.sh'] Element: 2 name: baz args: ['run.sh']
func (*RNode) Field ¶
Field returns a fieldName, fieldValue pair for MappingNodes. Returns nil for non-MappingNodes.
func (*RNode) FieldPath ¶
FieldPath returns the field path from the Resource root node, to rn. Does not include list indexes.
func (*RNode) Fields ¶
Fields returns the list of field names for a MappingNode. Returns an error for non-MappingNodes.
func (*RNode) GetAssociativeKey ¶
GetAssociativeKey returns the AssociativeSequenceKey used to merge the elements in the SequenceNode, or "" if the list is not associative.
func (*RNode) GetMeta ¶
func (rn *RNode) GetMeta() (ResourceMeta, error)
GetMeta returns the ResourceMeta for an RNode
func (*RNode) IsAssociative ¶
IsAssociative returns true if the RNode contains an AssociativeSequenceKey as a field.
func (*RNode) MarshalJSON ¶ added in v0.1.5
func (*RNode) MustString ¶
MustString returns string representation of the RNode or panics if there is an error
func (*RNode) Pipe ¶
Pipe sequentially invokes each GrepFilter, and passes the result to the next GrepFilter.
Analogous to http://www.linfo.org/pipes.html
* rn is provided as input to the first GrepFilter. * if any GrepFilter returns an error, immediately return the error * if any GrepFilter returns a nil RNode, immediately return nil, nil * if all Filters succeed with non-empty results, return the final result
func (*RNode) PipeE ¶
PipeE runs Pipe, dropping the *RNode return value. Useful for directly returning the Pipe error value from functions.
func (*RNode) SetYNode ¶
func (rn *RNode) SetYNode(node *yaml.Node)
SetYNode sets the yaml.Node value on an RNode.
func (*RNode) UnmarshalJSON ¶ added in v0.1.5
func (*RNode) VisitElements ¶
VisitElements calls fn for each element in a SequenceNode. Returns an error for non-SequenceNodes
func (*RNode) VisitFields ¶
VisitFields calls fn for each field in the RNode. Returns an error for non-MappingNodes.
type ResourceIdentifier ¶
type ResourceIdentifier struct { // Name is the name of the resource as set in metadata.name Name string `yaml:"name,omitempty"` // Namespace is the namespace of the resource as set in metadata.namespace Namespace string `yaml:"namespace,omitempty"` // ApiVersion is the apiVersion of the resource APIVersion string `yaml:"apiVersion,omitempty"` // Kind is the kind of the resource Kind string `yaml:"kind,omitempty"` }
ResourceIdentifier contains the information needed to uniquely identify a resource in a cluster.
func (*ResourceIdentifier) GetAPIVersion ¶
func (r *ResourceIdentifier) GetAPIVersion() string
func (*ResourceIdentifier) GetKind ¶
func (r *ResourceIdentifier) GetKind() string
func (*ResourceIdentifier) GetName ¶
func (r *ResourceIdentifier) GetName() string
func (*ResourceIdentifier) GetNamespace ¶
func (r *ResourceIdentifier) GetNamespace() string
type ResourceMeta ¶
type ResourceMeta struct { // APIVersion is the apiVersion field of a Resource APIVersion string `yaml:"apiVersion,omitempty"` // Kind is the kind field of a Resource Kind string `yaml:"kind,omitempty"` // ObjectMeta is the metadata field of a Resource ObjectMeta `yaml:"metadata,omitempty"` }
ResourceMeta contains the metadata for a both Resource Type and Resource.
func (*ResourceMeta) GetIdentifier ¶
func (m *ResourceMeta) GetIdentifier() ResourceIdentifier
GetIdentifier returns a ResourceIdentifier that includes the information needed to uniquely identify a resource in a cluster.
type SuffixSetter ¶
type TeePiper ¶
type TeePiper struct { Kind string `yaml:"kind,omitempty"` // Filters are the set of Filters run by TeePiper. Filters []Filter `yaml:"filters,omitempty"` }
TeePiper Calls a slice of Filters and returns its input. May be used to fork sub-filters from a call. e.g. locate field, set value; locate another field, set another value
type Unmarshaler ¶
type Unmarshaler = yaml.Unmarshaler
type ValueReplacer ¶
type YFilter ¶
type YFilter struct {
Filter
}
YFilter wraps the GrepFilter interface so the filter can be represented as data and can be unmarshalled into a struct from a yaml config file. This allows Pipelines to be expressed as data rather than code.
func (YFilter) MarshalYAML ¶
func (*YFilter) UnmarshalYAML ¶
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package merge contains libraries for merging fields from one RNode to another RNode
|
Package merge contains libraries for merging fields from one RNode to another RNode |
Package merge contains libraries for merging fields from one RNode to another RNode
|
Package merge contains libraries for merging fields from one RNode to another RNode |
Package schema contains libraries for working with the yaml and openapi packages.
|
Package schema contains libraries for working with the yaml and openapi packages. |