~samwhited/xmpp

2a7c759280457d1868de50cc54d8acd3f1c1d6fe — Sam Whited 4 months ago 932069a
internal/integration/prosody: support MUC

Signed-off-by: Sam Whited <sam@samwhited.com>
M component/integration_test.go => component/integration_test.go +1 -1
@@ 26,7 26,7 @@ func TestIntegrationComponentClient(t *testing.T) {
	prosodyRun := prosody.Test(context.TODO(), t,
		integration.Log(),
		prosody.ListenC2S(),
		prosody.Component(domain, secret),
		prosody.Component(domain, secret, ""),
	)
	prosodyRun(integrationComponentClient)
}

M internal/integration/prosody/config.go => internal/integration/prosody/config.go +9 -4
@@ 22,7 22,11 @@ type Config struct {
	Modules   []string
	VHosts    []string
	Options   map[string]interface{}
	Component map[string]string
	Component map[string]struct {
		Name    string
		Secret  string
		Modules []string
	}
}

const cfgBase = `daemonize = false


@@ 104,9 108,10 @@ certificates = "{{ .ConfigDir }}"
VirtualHost "{{ . }}"
{{- end }}

{{ range $domain, $secret := .Component }}
Component "{{$domain}}"
         component_secret = "{{$secret}}"
{{ range $domain, $cfg := .Component }}
Component "{{$domain}}" {{if $cfg.Name}}"{{$cfg.Name}}"{{end}}
				 {{if $cfg.Modules}}modules_enabled = { {{ luaList $cfg.Modules }} }{{end}}
				 {{if $cfg.Secret}}component_secret = "{{$cfg.Secret}}"{{end}}
{{ end }}`

var cfgTmpl = template.Must(template.New("cfg").Funcs(template.FuncMap{

M internal/integration/prosody/prosody.go => internal/integration/prosody/prosody.go +40 -23
@@ 163,33 163,50 @@ func VHost(hosts ...string) integration.Option {
	}
}

// Component adds an external component with the given domain and secret to the
// config file.
func Component(domain, secret string) integration.Option {
	return func(cmd *integration.Cmd) error {
		compListener, err := cmd.ComponentListen("tcp", "[::1]:0")
		if err != nil {
			return err
		}
		// Prosody creates its own sockets and doesn't provide us with a way of
		// pointing it at an existing Unix domain socket or handing the filehandle
		// for the TCP connection to it on start, so we're effectively just
		// listening to get a random port that we'll use to configure Prosody, then
		// we need to close the connection and let Prosody listen on that port.
		// Technically this is racey, but it's not likely to be a problem in
		// practice.
		compPort := compListener.Addr().(*net.TCPAddr).Port
		err = compListener.Close()
		if err != nil {
			return err
		}
// MUC launches prosody with the built-in multi-user chat component enabled.
// It is the same as Component(domain, "", "muc", modules).
func MUC(domain string, modules ...string) integration.Option {
	return Component(domain, "", "muc", modules...)
}

// Component adds an component with the given domain and secret to the config
// file.
// If a name is provided the component must be a builtin.
func Component(domain, secret, name string, modules ...string) integration.Option {
	return func(cmd *integration.Cmd) error {
		cfg := getConfig(cmd)
		cfg.CompPort = compPort
		if name == "" {
			compListener, err := cmd.ComponentListen("tcp", "[::1]:0")
			if err != nil {
				return err
			}
			// Prosody creates its own sockets and doesn't provide us with a way of
			// pointing it at an existing Unix domain socket or handing the filehandle
			// for the TCP connection to it on start, so we're effectively just
			// listening to get a random port that we'll use to configure Prosody, then
			// we need to close the connection and let Prosody listen on that port.
			// Technically this is racey, but it's not likely to be a problem in
			// practice.
			compPort := compListener.Addr().(*net.TCPAddr).Port
			err = compListener.Close()
			if err != nil {
				return err
			}

			cfg.CompPort = compPort
		}
		if cfg.Component == nil {
			cfg.Component = make(map[string]string)
			cfg.Component = make(map[string]struct {
				Name    string
				Secret  string
				Modules []string
			})
		}
		cfg.Component[domain] = secret
		comp := cfg.Component[domain]
		comp.Secret = secret
		comp.Name = name
		comp.Modules = modules
		cfg.Component[domain] = comp
		cmd.Config = cfg
		return nil
	}