ModuleFromNode does all work to create or get existing module object with a certain type. It is not used by top-level module definitions, only for references from other modules configuration blocks. inlineCfg should contain configuration directives for inline declarations. args should contain value
(preferredNamespace string, args []string, inlineCfg config.Node, globals map[string]interface{}, moduleIface interface{})
| 100 | // Module with name preferredNamespace + "." + args[0] will be preferred over just args[0]. |
| 101 | // It can be omitted. |
| 102 | func ModuleFromNode(preferredNamespace string, args []string, inlineCfg config.Node, globals map[string]interface{}, moduleIface interface{}) error { |
| 103 | if len(args) == 0 { |
| 104 | return parser.NodeErr(inlineCfg, "at least one argument is required") |
| 105 | } |
| 106 | |
| 107 | referenceExisting := strings.HasPrefix(args[0], "&") |
| 108 | |
| 109 | var modObj module.Module |
| 110 | var err error |
| 111 | if referenceExisting { |
| 112 | if len(args) != 1 || inlineCfg.Children != nil { |
| 113 | return parser.NodeErr(inlineCfg, "exactly one argument is required to use existing config block") |
| 114 | } |
| 115 | modObj, err = container.Global.Modules.Get(args[0][1:]) |
| 116 | log.Debugf("%s:%d: reference %s", inlineCfg.File, inlineCfg.Line, args[0]) |
| 117 | } else { |
| 118 | log.Debugf("%s:%d: new module %s %v", inlineCfg.File, inlineCfg.Line, args[0], args[1:]) |
| 119 | modObj, err = createInlineModule(container.Global, preferredNamespace, args[0]) |
| 120 | } |
| 121 | if err != nil { |
| 122 | return err |
| 123 | } |
| 124 | |
| 125 | // NOTE: This will panic if moduleIface is not a pointer. |
| 126 | modIfaceType := reflect.TypeOf(moduleIface).Elem() |
| 127 | modObjType := reflect.TypeOf(modObj) |
| 128 | |
| 129 | if modIfaceType.Kind() == reflect.Interface { |
| 130 | // Case for assignment to module interface type. |
| 131 | if !modObjType.Implements(modIfaceType) && !modObjType.AssignableTo(modIfaceType) { |
| 132 | return parser.NodeErr(inlineCfg, "module %s (%s) doesn't implement %v interface", modObj.Name(), modObj.InstanceName(), modIfaceType) |
| 133 | } |
| 134 | } else if !modObjType.AssignableTo(modIfaceType) { |
| 135 | // Case for assignment to concrete module type. Used in "module groups". |
| 136 | return parser.NodeErr(inlineCfg, "module %s (%s) is not %v", modObj.Name(), modObj.InstanceName(), modIfaceType) |
| 137 | } |
| 138 | |
| 139 | reflect.ValueOf(moduleIface).Elem().Set(reflect.ValueOf(modObj)) |
| 140 | |
| 141 | if !referenceExisting { |
| 142 | if err := configureInlineModule(modObj, args[1:], globals, inlineCfg); err != nil { |
| 143 | return err |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | return nil |
| 148 | } |
| 149 | |
| 150 | // GroupFromNode provides a special kind of ModuleFromNode syntax that allows |
| 151 | // to omit the module name when defining inine configuration. If it is not |
no test coverage detected