Files
podman/pkg/machine/connection/connection.go
Jake Correnti 24deec835c Update connection on removal
Modify `RemoveConnections` to verify the new default system connection's
rootful state matches the rootful-ness of the podman machine it is associated
with.

Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me>
2024-09-24 15:46:02 -04:00

164 lines
4.2 KiB
Go

//go:build amd64 || arm64
package connection
import (
"errors"
"fmt"
"net"
"net/url"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v5/pkg/machine/define"
)
const LocalhostIP = "127.0.0.1"
type connection struct {
name string
uri *url.URL
}
func addConnection(cons []connection, identity string, isDefault bool) error {
if len(identity) < 1 {
return errors.New("identity must be defined")
}
return config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error {
for i, con := range cons {
if _, ok := cfg.Connection.Connections[con.name]; ok {
return fmt.Errorf("cannot overwrite connection %q", con.name)
}
dst := config.Destination{
URI: con.uri.String(),
IsMachine: true,
Identity: identity,
}
if isDefault && i == 0 {
cfg.Connection.Default = con.name
}
if cfg.Connection.Connections == nil {
cfg.Connection.Connections = map[string]config.Destination{
con.name: dst,
}
cfg.Connection.Default = con.name
} else {
cfg.Connection.Connections[con.name] = dst
}
}
return nil
})
}
func UpdateConnectionPairPort(name string, port, uid int, remoteUsername string, identityPath string) error {
cons := createConnections(name, uid, port, remoteUsername)
return config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error {
for _, con := range cons {
dst := config.Destination{
IsMachine: true,
URI: con.uri.String(),
Identity: identityPath,
}
cfg.Connection.Connections[con.name] = dst
}
return nil
})
}
// UpdateConnectionIfDefault updates the default connection to the rootful/rootless when depending
// on the bool but only if other rootful/less connection was already the default.
// Returns true if it modified the default
func UpdateConnectionIfDefault(rootful bool, name, rootfulName string) error {
return config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error {
updateConnection(cfg, rootful, name, rootfulName)
return nil
})
}
func updateConnection(cfg *config.ConnectionsFile, rootful bool, name, rootfulName string) {
if name == cfg.Connection.Default && rootful {
cfg.Connection.Default = rootfulName
} else if rootfulName == cfg.Connection.Default && !rootful {
cfg.Connection.Default = name
}
}
func RemoveConnections(machines map[string]bool, names ...string) error {
var dest config.Destination
var service string
if err := config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error {
err := setNewDefaultConnection(cfg, &dest, &service, names...)
if err != nil {
return err
}
rootful, ok := machines[service]
if dest.IsMachine && ok {
updateConnection(cfg, rootful, service, service+"-root")
}
return nil
}); err != nil {
return err
}
return nil
}
// setNewDefaultConnection iterates through the available system connections and
// sets the first available connection as the new default
func setNewDefaultConnection(cfg *config.ConnectionsFile, dest *config.Destination, service *string, names ...string) error {
// delete the connection associated with the names and if that connection is
// the default, reset the default connection
for _, name := range names {
if _, ok := cfg.Connection.Connections[name]; ok {
delete(cfg.Connection.Connections, name)
} else {
return fmt.Errorf("unable to find connection named %q", name)
}
if cfg.Connection.Default == name {
cfg.Connection.Default = ""
}
}
// If there is a podman-machine-default system connection, immediately set that as the new default
if c, ok := cfg.Connection.Connections[define.DefaultMachineName]; ok {
cfg.Connection.Default = define.DefaultMachineName
*dest = c
*service = define.DefaultMachineName
return nil
}
// set the new default system connection to the first in the map
for con, d := range cfg.Connection.Connections {
cfg.Connection.Default = con
*dest = d
*service = con
break
}
return nil
}
// makeSSHURL creates a URL from the given input
func makeSSHURL(host, path, port, userName string) *url.URL {
var hostname string
if len(port) > 0 {
hostname = net.JoinHostPort(host, port)
} else {
hostname = host
}
userInfo := url.User(userName)
return &url.URL{
Scheme: "ssh",
User: userInfo,
Host: hostname,
Path: path,
}
}