예제 #1
0
func FindUnresolvedNodes(root yaml.Node, context ...string) (nodes []UnresolvedNode) {
	if root == nil {
		return nodes
	}

	switch val := root.Value().(type) {
	case map[string]yaml.Node:
		for key, val := range val {
			nodes = append(
				nodes,
				FindUnresolvedNodes(val, addContext(context, key)...)...,
			)
		}

	case []yaml.Node:
		for i, val := range val {
			context := addContext(context, fmt.Sprintf("[%d]", i))

			nodes = append(
				nodes,
				FindUnresolvedNodes(val, context...)...,
			)
		}

	case Expression:
		var path []string
		switch val := root.Value().(type) {
		case AutoExpr:
			path = val.Path
		case MergeExpr:
			path = val.Path
		}

		nodes = append(nodes, UnresolvedNode{
			Node:    root,
			Context: context,
			Path:    path,
		})

	case string:
		if yaml.EmbeddedDynaml(root) != nil {
			nodes = append(nodes, UnresolvedNode{
				Node:    yaml.IssueNode(root, "unparseable expression"),
				Context: context,
				Path:    []string{},
			})
		}
	}

	return nodes
}
예제 #2
0
파일: flow_test.go 프로젝트: gstackio/spiff
		})
	})

	Context("when some dynaml nodes cannot be resolved", func() {
		It("returns an error", func() {
			source := parseYAML(`
---
foo: (( auto ))
`)

			_, err := Flow(source)
			Expect(err).To(Equal(dynaml.UnresolvedNodes{
				Nodes: []dynaml.UnresolvedNode{
					{
						Node: yaml.IssueNode(yaml.NewNode(
							dynaml.AutoExpr{Path: []string{"foo"}},
							"test",
						), "auto only allowed for size entry in resource pools"),
						Context: []string{"foo"},
						Path:    []string{"foo"},
					},
				},
			}))
		})
	})

	Context("when a reference is made to a yet-to-be-resolved node, in a || expression", func() {
		It("eventually resolves to the referenced node", func() {
			source := parseYAML(`
---
properties:
  template_only: (( merge ))
예제 #3
0
파일: flow.go 프로젝트: gstackio/spiff
func flow(root yaml.Node, env Environment, shouldOverride bool) yaml.Node {
	if root == nil {
		return root
	}

	replace := root.ReplaceFlag()
	redirect := root.RedirectPath()
	preferred := root.Preferred()
	merged := root.Merged()
	keyName := root.KeyName()

	if redirect != nil {
		env = env.RedirectOverwrite(redirect)
	}

	if !replace {
		switch val := root.Value().(type) {
		case map[string]yaml.Node:
			return flowMap(root, env)

		case []yaml.Node:
			return flowList(root, env)

		case dynaml.Expression:
			debug.Debug("??? eval %+v\n", val)
			result, info, ok := val.Evaluate(env)
			if !ok {
				root = yaml.IssueNode(root, info.Issue)
				debug.Debug("??? failed ---> KEEP\n")
				if !shouldOverride {
					return root
				}
				replace = replace || info.Replace
			} else {
				_, ok = result.Value().(string)
				if ok {
					// map result to potential expression
					result = flowString(result, env)
				}
				_, expr := result.Value().(dynaml.Expression)

				// preserve accumulated node attributes
				if preferred || info.Preferred {
					debug.Debug("   PREFERRED")
					result = yaml.PreferredNode(result)
				}

				if info.KeyName != "" {
					keyName = info.KeyName
					result = yaml.KeyNameNode(result, keyName)
				}
				if len(info.RedirectPath) > 0 {
					redirect = info.RedirectPath
				}
				if len(redirect) > 0 {
					debug.Debug("   REDIRECT -> %v\n", redirect)
					result = yaml.RedirectNode(result.Value(), result, redirect)
				}

				if replace || info.Replace {
					debug.Debug("   REPLACE\n")
					result = yaml.ReplaceNode(result.Value(), result, redirect)
				} else {
					if merged || info.Merged {
						debug.Debug("   MERGED\n")
						result = yaml.MergedNode(result)
					}
				}
				if expr || result.Merged() || !shouldOverride || result.Preferred() {
					debug.Debug("   prefer expression over override")
					debug.Debug("??? ---> %+v\n", result)
					return result
				}
				debug.Debug("???   try override")
				replace = result.ReplaceFlag()
				root = result
			}

		case string:
			result := flowString(root, env)
			if result != nil {
				_, ok := result.Value().(dynaml.Expression)
				if ok {
					// analyse expression before overriding
					return result
				}
			}
		}
	}

	if !merged && shouldOverride {
		debug.Debug("/// lookup stub %v -> %v\n", env.Path, env.StubPath)
		overridden, found := env.FindInStubs(env.StubPath)
		if found {
			root = overridden
			if keyName != "" {
				root = yaml.KeyNameNode(root, keyName)
			}
			if replace {
				return yaml.ReplaceNode(root.Value(), root, redirect)
			}
			if redirect != nil {
				return yaml.RedirectNode(root.Value(), root, redirect)
			}
			if merged {
				return yaml.MergedNode(root)
			}
		}
	}

	return root
}