variable

package
v4.0.3 Latest Latest
Warning

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

Go to latest
Published: Jan 14, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Overview

Package variable provides functionality for handling variables in YAML format.

Index

Constants

This section is empty.

Variables

View Source
var GetAllVariable = func(hostname string) GetFunc {

	getLocalIP := func(ipType string) string {
		addrs, err := net.InterfaceAddrs()
		if err != nil {
			klog.ErrorS(err, "get network address error")
		}

		for _, addr := range addrs {
			if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
				if ipType == _const.VariableIPv4 && ipNet.IP.To4() != nil {
					return ipNet.IP.String()
				}

				if ipType == _const.VariableIPv6 && ipNet.IP.To16() != nil && ipNet.IP.To4() == nil {
					return ipNet.IP.String()
				}
			}
		}

		klog.V(4).Infof("cannot get local %s address", ipType)

		return ""
	}

	defaultHostVariable := func(hostname string, hostVars map[string]any) {
		if hostname == _const.VariableLocalHost {
			if _, ok := hostVars[_const.VariableIPv4]; !ok {
				hostVars[_const.VariableIPv4] = getLocalIP(_const.VariableIPv4)
			}
			if _, ok := hostVars[_const.VariableIPv6]; !ok {
				hostVars[_const.VariableIPv6] = getLocalIP(_const.VariableIPv6)
			}
		}
		if os, ok := hostVars[_const.VariableOS]; ok {

			if osd, ok := os.(map[string]any); ok {
				hostVars[_const.VariableHostName] = osd[_const.VariableOSHostName]
			}
		}
		if _, ok := hostVars[_const.VariableInventoryName]; !ok {
			hostVars[_const.VariableInventoryName] = hostname
		}
		if _, ok := hostVars[_const.VariableHostName]; !ok {
			hostVars[_const.VariableHostName] = hostname
		}
	}

	getHostsVariable := func(v *variable) map[string]any {
		globalHosts := make(map[string]any)
		for hostname := range v.value.Hosts {
			hostVars := make(map[string]any)

			for _, gv := range v.value.Inventory.Spec.Groups {
				if slices.Contains(gv.Hosts, hostname) {
					hostVars = CombineVariables(hostVars, Extension2Variables(gv.Vars))
				}
			}

			hostVars = CombineVariables(hostVars, v.value.Hosts[hostname].RemoteVars)

			hostVars = CombineVariables(hostVars, v.value.Hosts[hostname].RuntimeVars)

			hostVars = CombineVariables(hostVars, Extension2Variables(v.value.Inventory.Spec.Vars))

			hostVars = CombineVariables(hostVars, Extension2Variables(v.value.Inventory.Spec.Hosts[hostname]))

			hostVars = CombineVariables(hostVars, Extension2Variables(v.value.Config.Spec))

			defaultHostVariable(hostname, hostVars)
			globalHosts[hostname] = hostVars
		}

		return globalHosts
	}

	return func(v Variable) (any, error) {
		vv, ok := v.(*variable)
		if !ok {
			return nil, errors.New("variable type error")
		}
		hosts := getHostsVariable(vv)
		hostVars, ok := hosts[hostname].(map[string]any)
		if !ok {

			return make(map[string]any), nil
		}

		hostVars = CombineVariables(hostVars, map[string]any{
			_const.VariableGlobalHosts: hosts,
		})

		hostVars = CombineVariables(hostVars, map[string]any{
			_const.VariableGroups: ConvertGroup(vv.value.Inventory),
		})

		return hostVars, nil
	}
}

GetAllVariable retrieves all variables for a given host, including group variables, remote variables, runtime variables, inventory variables, and configuration variables. It also sets default variables for localhost and provides access to global host and group information.

View Source
var GetHostMaxLength = func() GetFunc {
	return func(v Variable) (any, error) {
		vv, ok := v.(*variable)
		if !ok {
			return nil, errors.New("variable type error")
		}
		var hostnameMaxLen int
		for k := range vv.value.Hosts {
			hostnameMaxLen = max(len(k), hostnameMaxLen)
		}

		return hostnameMaxLen, nil
	}
}

GetHostMaxLength calculates the maximum length of all hostnames. This is useful for formatting output or determining display widths.

View Source
var GetHostnames = func(name []string) GetFunc {
	if len(name) == 0 {
		return emptyGetFunc
	}

	return func(v Variable) (any, error) {
		vv, ok := v.(*variable)
		if !ok {
			return nil, errors.New("variable type error")
		}
		var hs []string
		for _, n := range name {

			if pn, err := tmpl.ParseFunc(Extension2Variables(vv.value.Config.Spec), n, func(b []byte) string { return string(b) }); err == nil {
				n = pn
			}

			if _, exists := vv.value.Hosts[n]; exists {
				hs = append(hs, n)
			}

			for gn, gv := range ConvertGroup(vv.value.Inventory) {
				if gn == n {
					hs = CombineSlice(hs, gv)
					break
				}
			}

			regexForIndex := regexp.MustCompile(`^(.*?)\[(\d+)\]$`)
			if match := regexForIndex.FindStringSubmatch(strings.TrimSpace(n)); match != nil {
				index, err := strconv.Atoi(match[2])
				if err != nil {
					return nil, errors.Wrapf(err, "failed to convert %q to int", match[2])
				}
				if group, ok := ConvertGroup(vv.value.Inventory)[match[1]]; ok {
					if index >= len(group) {
						return nil, errors.Errorf("index %v out of range for group %s", index, group)
					}
					hs = append(hs, group[index])
				}
			}

			regexForRandom := regexp.MustCompile(`^(.+?)\s*\|\s*random$`)
			if match := regexForRandom.FindStringSubmatch(strings.TrimSpace(n)); match != nil {
				if group, ok := ConvertGroup(vv.value.Inventory)[match[1]]; ok {
					hs = append(hs, group[rand.Intn(len(group))])
				}
			}
		}

		return hs, nil
	}
}

GetHostnames retrieves all hostnames from specified groups or hosts. It supports various hostname patterns including direct hostnames, group names, indexed group access (e.g., "group[0]"), and random selection (e.g., "group|random"). The function also supports template parsing for hostnames using configuration variables.

View Source
var GetResultVariable = func() GetFunc {
	return func(v Variable) (any, error) {
		vv, ok := v.(*variable)
		if !ok {
			return nil, errors.New("variable type error")
		}

		return vv.value.Result[resultKey], nil
	}
}

GetResultVariable returns the global result variables. This function retrieves the result variables that are set globally and accessible across all hosts.

View Source
var GetWorkDir = func() GetFunc {
	return func(v Variable) (any, error) {
		vv, ok := v.(*variable)
		if !ok {
			return nil, errors.New("variable type error")
		}

		return _const.GetWorkdirFromConfig(vv.value.Config), nil
	}
}

GetWorkDir returns the working directory from the configuration.

View Source
var MergeHostsRuntimeVariable = func(node yaml.Node, hostname string, hosts ...string) MergeFunc {
	if node.IsZero() {

		return emptyMergeFunc
	}

	return func(v Variable) error {
		vv, ok := v.(*variable)
		if !ok {
			return errors.New("variable type error")
		}

		curVars, err := v.Get(GetAllVariable(hostname))
		if err != nil {
			return err
		}
		ctx, ok := curVars.(map[string]any)
		if !ok {
			return errors.Errorf("host %s variables type error, expect map[string]any", hostname)
		}
		data, err := parseYamlNode(ctx, node)
		if err != nil {
			return err
		}
		for _, h := range hosts {
			hv := vv.value.Hosts[h]
			hv.RuntimeVars = CombineVariables(hv.RuntimeVars, data)
			vv.value.Hosts[h] = hv
		}

		return nil
	}
}

MergeHostsRuntimeVariable parses variables using a specific host's context and merges them to multiple hosts' runtime variables. It takes a YAML node, a source hostname for context, and a list of target hostnames. The function uses the source host's variables as context to parse the YAML node, then merges the parsed data into each target host's RuntimeVars.

View Source
var MergeRemoteVariable = func(data map[string]any, hostnames ...string) MergeFunc {
	return func(v Variable) error {
		vv, ok := v.(*variable)
		if !ok {
			return errors.New("variable type error")
		}

		for _, hostname := range hostnames {
			if _, ok := vv.value.Hosts[hostname]; !ok {
				return errors.Errorf("when merge source is remote. HostName %s not exist", hostname)
			}

			hv := vv.value.Hosts[hostname]
			hv.RemoteVars = data
			vv.value.Hosts[hostname] = hv
		}

		return nil
	}
}

MergeRemoteVariable merges the provided data as remote variables into the specified hosts. For each hostname, if the host exists and its RemoteVars is empty, it sets RemoteVars to the provided data. If the host does not exist, it returns an error.

View Source
var MergeResultVariable = func(result any) MergeFunc {
	return func(v Variable) error {
		vv, ok := v.(*variable)
		if !ok {
			return errors.New("variable type error")
		}

		vv.value.Result = CombineVariables(vv.value.Result, map[string]any{resultKey: result})

		return nil
	}
}

MergeResultVariable parses variables using a specific host's context and sets them as global result variables. It takes a YAML node and a hostname, then: 1. Gets all variables for the host to create a parsing context 2. Parses the YAML node using that context 3. Sets the parsed data as the global result variables (accessible across all hosts)

View Source
var MergeRuntimeVariable = func(nodes []yaml.Node, hosts ...string) MergeFunc {
	if len(nodes) == 0 {

		return emptyMergeFunc
	}

	return func(v Variable) error {
		for _, hostname := range hosts {
			vv, ok := v.(*variable)
			if !ok {
				return errors.New("variable type error")
			}

			curVars, err := v.Get(GetAllVariable(hostname))
			if err != nil {
				return err
			}
			ctx, ok := curVars.(map[string]any)
			if !ok {
				return errors.Errorf("host %s variables type error, expect map[string]any", hostname)
			}
			for _, node := range nodes {
				if node.IsZero() {
					continue
				}
				data, err := parseYamlNode(ctx, node)
				if err != nil {
					return err
				}
				hv := vv.value.Hosts[hostname]
				hv.RuntimeVars = CombineVariables(hv.RuntimeVars, data)
				vv.value.Hosts[hostname] = hv
			}
		}

		return nil
	}
}

MergeRuntimeVariable parses variables using a specific host's context and merges them to the host's runtime variables. It takes a YAML node and a list of hostnames, then for each host: 1. Gets all variables for the host to create a parsing context 2. Parses the YAML node using that context 3. Merges the parsed data into the host's RuntimeVars

Functions

func AnyVar

func AnyVar(ctx, args map[string]any, dest any, keys ...string) error

AnyVar get data from input args and keys,unmarshal data into dest

func BoolVar

func BoolVar(ctx map[string]any, args map[string]any, keys ...string) (*bool, error)

BoolVar get bool value by key

func CombineSlice

func CombineSlice(g1, g2 []string) []string

CombineSlice combines two string slices while skipping duplicate values. It maintains the order of elements from g1 followed by unique elements from g2.

Parameters:

  • g1: The first slice of strings
  • g2: The second slice of strings

Returns:

  • A new slice containing unique strings from both input slices, preserving order with g1 elements appearing before unique g2 elements

func CombineVariables

func CombineVariables(m1, m2 map[string]any) map[string]any

CombineVariables merge multiple variables into one variable. It recursively combines two maps, where values from m2 override values from m1 if keys overlap. For nested maps, it will recursively merge their contents. For non-map values or when either input is nil, m2's value takes precedence.

Parameters:

  • m1: The first map to merge (base map)
  • m2: The second map to merge (override map)

Returns:

  • A new map containing the merged key-value pairs from both input maps

func ConvertGroup

func ConvertGroup(inv kkcorev1.Inventory) map[string][]string

ConvertGroup converts the inventory into a map of groups with their respective hosts. It ensures that all hosts are included in the "all" group and adds a default localhost if not present. It also creates an "ungrouped" group for hosts that are not part of any specific group.

Parameters:

inv (kkcorev1.Inventory): The inventory containing hosts and groups specifications.

Returns:

map[string][]string: A map where keys are group names and values are lists of hostnames.

func CreateValueNode added in v4.0.3

func CreateValueNode(v any) (*yaml.Node, error)

CreateValueNode generate yaml node by input anything

func DurationVar

func DurationVar(ctx map[string]any, args map[string]any, key string) (time.Duration, error)

DurationVar get time.Duration value by key

func Extension2Slice

func Extension2Slice(ctx map[string]any, ext runtime.RawExtension) []any

Extension2Slice convert runtime.RawExtension to slice if runtime.RawExtension contains tmpl syntax, parse it.

func Extension2String

func Extension2String(ctx map[string]any, ext runtime.RawExtension) ([]byte, error)

Extension2String converts a runtime.RawExtension to a string, optionally parsing it as a template. If the extension is empty, it returns nil. If the string is quoted, it unquotes it first. Finally, it parses the string as a template using the provided context.

func Extension2Variables

func Extension2Variables(ext runtime.RawExtension) map[string]any

Extension2Variables convert runtime.RawExtension to variables

func IntVar

func IntVar(ctx map[string]any, args map[string]any, keys ...string) (*int, error)

IntVar get int value by key

func PrintVar

func PrintVar(ctx map[string]any, keys ...string) (any, error)

PrintVar get variable by key

func StringSliceVar

func StringSliceVar(ctx map[string]any, args map[string]any, keys ...string) ([]string, error)

StringSliceVar get string slice value by key

func StringVar

func StringVar(ctx map[string]any, args map[string]any, keys ...string) (string, error)

StringVar get string value by key

Types

type GetFunc

type GetFunc func(Variable) (any, error)

GetFunc get data from variable

type MergeFunc

type MergeFunc func(Variable) error

MergeFunc merge data to variable

type Variable

type Variable interface {
	Get(getFunc GetFunc) (any, error)
	Merge(mergeFunc MergeFunc) error
}

Variable store all vars which playbook used.

func New

func New(ctx context.Context, client ctrlclient.Client, playbook kkcorev1.Playbook, st source.SourceType) (Variable, error)

New variable. generate value from config args. and render to source.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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