~samwhited/xmpp

7ae6a6965284f20edbf327f7b5588bc081b12b70 — Sam Whited 9 months ago eff9a17
internal/integration/prosody: component support

Signed-off-by: Sam Whited <sam@samwhited.com>
2 files changed, 46 insertions(+), 7 deletions(-)

M internal/integration/prosody/config.go
M internal/integration/prosody/prosody.go
M internal/integration/prosody/config.go => internal/integration/prosody/config.go +15 -7
@@ 13,12 13,14 @@ import (

// Config contains options that can be written to a Prosody config file.
type Config struct {
	C2SPort int
	S2SPort int
	Admins  []string
	Modules []string
	VHosts  []string
	Options map[string]interface{}
	C2SPort   int
	S2SPort   int
	CompPort  int
	Admins    []string
	Modules   []string
	VHosts    []string
	Options   map[string]interface{}
	Component map[string]string
}

const cfgBase = `daemonize = false


@@ 28,6 30,7 @@ data_path = "{{ .ConfigDir }}"
interfaces = { "::1" }
{{ if .C2SPort }}c2s_ports = { {{ .C2SPort }} }{{ end }}
{{ if .S2SPort }}s2s_ports = { {{ .S2SPort }} }{{ end }}
{{ if .CompPort }}component_ports = { {{.CompPort}} }{{ end }}

-- Settings added with prosody.Set:
{{ range $k, $opt := .Options }}


@@ 89,7 92,12 @@ certificates = "{{ .ConfigDir }}"

{{- range .VHosts }}
VirtualHost "{{ . }}"
{{- end }}`
{{- end }}

{{ range $domain, $secret := .Component }}
Component "{{$domain}}"
         component_secret = "{{$secret}}"
{{ end }}`

var cfgTmpl = template.Must(template.New("cfg").Funcs(template.FuncMap{
	"filepathJoin": filepath.Join,

M internal/integration/prosody/prosody.go => internal/integration/prosody/prosody.go +31 -0
@@ 146,6 146,37 @@ 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
		}

		cfg := getConfig(cmd)
		cfg.CompPort = compPort
		if cfg.Component == nil {
			cfg.Component = make(map[string]string)
		}
		cfg.Component[domain] = secret
		cmd.Config = cfg
		return nil
	}
}

// CreateUser returns an option that calls prosodyctl to create a user.
// It is equivalent to calling:
// Ctl(ctx, "register", "localpart", "domainpart", "password") except that it