2024-03-12 05:35:32 +00:00
|
|
|
package host
|
|
|
|
|
|
|
|
import (
|
2024-04-21 18:42:59 +00:00
|
|
|
"errors"
|
2024-03-12 05:35:32 +00:00
|
|
|
"strings"
|
2024-03-24 04:05:06 +00:00
|
|
|
|
2024-04-07 06:00:59 +00:00
|
|
|
log "git.staur.ca/stobbsm/simplelog"
|
2024-03-12 05:35:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// URI is a string type, accessed via the pre-defined variables, and represent
|
|
|
|
// the URI pattern used to connect to a host.
|
|
|
|
// Example:
|
|
|
|
// Driver[+Transport]://<host or empty for local>[:PORT]/<path>[?Options&in=uri&format]
|
|
|
|
type URI struct {
|
|
|
|
Driver string
|
|
|
|
Transport string
|
|
|
|
Path string
|
2024-04-20 05:37:21 +00:00
|
|
|
Host string
|
2024-03-12 05:35:32 +00:00
|
|
|
Options []string
|
|
|
|
}
|
|
|
|
|
2024-04-21 18:42:59 +00:00
|
|
|
// Define create and return a custom URI method, following RFC2396,
|
2024-03-12 05:35:32 +00:00
|
|
|
// keeping in mind that the hostname will be inserted between the transport and path
|
2024-04-21 18:42:59 +00:00
|
|
|
func Define(driver, transport, path string, options ...string) *URI {
|
2024-03-12 05:35:32 +00:00
|
|
|
return &URI{
|
|
|
|
Driver: driver,
|
|
|
|
Transport: transport,
|
|
|
|
Path: path,
|
|
|
|
Options: options,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-21 18:42:59 +00:00
|
|
|
var (
|
|
|
|
URI_QEMU_LOCAL = Define("qemu", "local", "system")
|
|
|
|
URI_QEMU_SSH = Define("qemu", "ssh", "system")
|
|
|
|
)
|
|
|
|
|
2024-04-20 05:37:21 +00:00
|
|
|
// WithHost sets the hostname as part of a URI. It copies the original URI and returns a new one
|
|
|
|
func (u *URI) WithHost(host string) *URI {
|
|
|
|
return &URI{
|
|
|
|
Driver: u.Driver,
|
|
|
|
Transport: u.Transport,
|
|
|
|
Path: u.Path,
|
|
|
|
Host: host,
|
|
|
|
Options: u.Options,
|
|
|
|
}
|
|
|
|
}
|
2024-03-12 05:35:32 +00:00
|
|
|
|
2024-04-20 05:37:21 +00:00
|
|
|
// IsRemote returns true if the URI references a remote trasnport (ssh, tcp or tls)
|
|
|
|
func (u *URI) IsRemote() bool {
|
|
|
|
switch u.Transport {
|
|
|
|
case "ssh":
|
|
|
|
fallthrough
|
|
|
|
case "tls":
|
|
|
|
fallthrough
|
|
|
|
case "tcp":
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// validTransport makes sure the value of transport if valid or empty. If the transport
|
|
|
|
// isn't remote, it returns an empty string
|
2024-04-21 18:42:59 +00:00
|
|
|
func (u *URI) validTransport() bool {
|
2024-04-20 05:37:21 +00:00
|
|
|
if u.IsRemote() {
|
2024-04-21 18:42:59 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
switch u.Transport {
|
|
|
|
case "unix":
|
|
|
|
fallthrough
|
|
|
|
case "local":
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
2024-04-20 05:37:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *URI) validDriver() bool {
|
|
|
|
switch u.Driver {
|
|
|
|
case "qemu":
|
|
|
|
fallthrough
|
|
|
|
case "xen":
|
2024-04-21 18:42:59 +00:00
|
|
|
fallthrough
|
|
|
|
case "lxc":
|
2024-04-20 05:37:21 +00:00
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2024-03-12 05:35:32 +00:00
|
|
|
|
|
|
|
// ConnectionString takes a host name to interpolate into a URI and returns the string
|
2024-04-20 05:37:21 +00:00
|
|
|
func (u *URI) ConnectionString() string {
|
|
|
|
// Normalize the variables
|
|
|
|
var driver, transport, path, host string
|
2024-04-21 18:42:59 +00:00
|
|
|
if !u.validTransport() {
|
|
|
|
log.Panic("host.URI.ConnectionString").
|
|
|
|
Err(errors.New("invalid transport")).
|
|
|
|
Str("transport", u.Transport).
|
|
|
|
Send()
|
2024-04-20 05:37:21 +00:00
|
|
|
}
|
2024-04-21 18:42:59 +00:00
|
|
|
transport = u.Transport
|
|
|
|
if (u.Host == "localhost" && u.IsRemote()) || u.Host != "localhost" {
|
2024-04-20 05:37:21 +00:00
|
|
|
host = u.Host
|
|
|
|
}
|
|
|
|
// TODO: validate driver, path
|
2024-04-21 18:42:59 +00:00
|
|
|
if !u.validDriver() {
|
|
|
|
log.Panic("host.URI.ConnectionString").
|
|
|
|
Err(errors.New("invalid driver")).
|
|
|
|
Str("driver", u.Driver).
|
|
|
|
Send()
|
|
|
|
}
|
2024-04-20 05:37:21 +00:00
|
|
|
driver = u.Driver
|
|
|
|
path = u.Path
|
|
|
|
|
2024-03-12 05:35:32 +00:00
|
|
|
var sb strings.Builder
|
|
|
|
optlen := len(u.Options)
|
2024-04-20 05:37:21 +00:00
|
|
|
sb.WriteString(driver)
|
|
|
|
if transport != "" {
|
2024-03-12 05:35:32 +00:00
|
|
|
sb.WriteRune('+')
|
|
|
|
sb.WriteString(u.Transport)
|
|
|
|
}
|
|
|
|
sb.WriteString("://")
|
2024-04-20 05:37:21 +00:00
|
|
|
if host != "" {
|
|
|
|
sb.WriteString(host)
|
2024-03-12 05:35:32 +00:00
|
|
|
}
|
|
|
|
sb.WriteRune('/')
|
2024-04-20 05:37:21 +00:00
|
|
|
sb.WriteString(path)
|
2024-03-12 05:35:32 +00:00
|
|
|
|
|
|
|
if optlen > 0 {
|
|
|
|
sb.WriteRune('?')
|
|
|
|
for i, o := range u.Options {
|
|
|
|
sb.WriteString(o)
|
|
|
|
if optlen != i+1 {
|
|
|
|
sb.WriteRune('&')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-24 04:05:06 +00:00
|
|
|
log.Info("Host.ConnectionString").
|
|
|
|
Str("uri.Driver", u.Driver).
|
|
|
|
Str("uri.Transport", u.Transport).
|
|
|
|
Str("uri.Path", u.Path).
|
|
|
|
Strs("uri.Options", u.Options).
|
|
|
|
Str("builtUri", sb.String()).Send()
|
2024-03-12 05:35:32 +00:00
|
|
|
return sb.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddOpt adds more options to the option list
|
|
|
|
func (u *URI) AddOpt(opt string) {
|
|
|
|
u.Options = append(u.Options, opt)
|
|
|
|
}
|