package policy import ( "errors" "net/netip" "go.starlark.net/starlark" ) // MDA implements starlark.Value and starlark.HasAttrs // so it can be exposed as the `mda` global object in the script. type MDA struct { parsedListeners []ListenerConfig } func (m *MDA) String() string { return "" } func (m *MDA) Type() string { return "module" } func (m *MDA) Freeze() {} func (m *MDA) Truth() starlark.Bool { return true } func (m *MDA) Hash() (uint32, error) { return 0, errors.New("unhashable") } func (m *MDA) Attr(name string) (starlark.Value, error) { switch name { case "listen": return starlark.NewBuiltin("listen", m.mdaListen), nil } return nil, nil } func (m *MDA) AttrNames() []string { return []string{"listen"} } // mdaListen handles mda.listen(address="...", role="...") func (m *MDA) mdaListen(_ *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { var address, role, tlsCertFile, tlsKeyFile string // starlark.UnpackArgs maps Starlark arguments to Go variables safely err := starlark.UnpackArgs( b.Name(), args, kwargs, "address", &address, "role", &role, "tls_cert_file", &tlsCertFile, "tls_key_file", &tlsKeyFile) if err != nil { return nil, err } addrPort, err := netip.ParseAddrPort(address) if err != nil { return nil, err } // Save to our Go state m.parsedListeners = append(m.parsedListeners, ListenerConfig{ Address: addrPort, Role: role, TLSCertFile: tlsCertFile, TLSKeyFile: tlsKeyFile, }) return starlark.None, nil }