mirror of
https://github.com/containers/podman.git
synced 2025-07-17 17:43:23 +08:00
rework system connection and farm storage
We now no longer write containers.conf, instead system connections and farms are written to a new file called podman-connections.conf. This is a major rework and I had to change a lot of things to get this to compile again with my c/common changes. It is a breaking change for users as connections/farms added before this commit can now no longer be removed or modified directly. However because the logic keeps reading from containers.conf the old connections can still be used to connect to a remote host. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
86
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
86
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
@ -9,11 +9,9 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containers/common/internal/attributedstring"
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/common/pkg/capabilities"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/containers/storage/pkg/unshare"
|
||||
units "github.com/docker/go-units"
|
||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||
@ -667,9 +665,9 @@ type MachineConfig struct {
|
||||
// FarmConfig represents the "farm" TOML config tables
|
||||
type FarmConfig struct {
|
||||
// Default is the default farm to be used when farming out builds
|
||||
Default string `toml:"default,omitempty"`
|
||||
Default string `json:",omitempty" toml:"default,omitempty"`
|
||||
// List is a map of farms created where key=farm-name and value=list of connections
|
||||
List map[string][]string `toml:"list,omitempty"`
|
||||
List map[string][]string `json:",omitempty" toml:"list,omitempty"`
|
||||
}
|
||||
|
||||
// Destination represents destination for remote service
|
||||
@ -678,10 +676,10 @@ type Destination struct {
|
||||
URI string `toml:"uri"`
|
||||
|
||||
// Identity file with ssh key, optional
|
||||
Identity string `toml:"identity,omitempty"`
|
||||
Identity string `json:",omitempty" toml:"identity,omitempty"`
|
||||
|
||||
// isMachine describes if the remote destination is a machine.
|
||||
IsMachine bool `toml:"is_machine,omitempty"`
|
||||
IsMachine bool `json:",omitempty" toml:"is_machine,omitempty"`
|
||||
}
|
||||
|
||||
// Consumes container image's os and arch and returns if any dedicated runtime was
|
||||
@ -1008,82 +1006,6 @@ func IsValidDeviceMode(mode string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func rootlessConfigPath() (string, error) {
|
||||
if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
return filepath.Join(configHome, _configPath), nil
|
||||
}
|
||||
home, err := unshare.HomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filepath.Join(home, UserOverrideContainersConfig), nil
|
||||
}
|
||||
|
||||
func Path() string {
|
||||
if path := os.Getenv("CONTAINERS_CONF"); path != "" {
|
||||
return path
|
||||
}
|
||||
if unshare.IsRootless() {
|
||||
if rpath, err := rootlessConfigPath(); err == nil {
|
||||
return rpath
|
||||
}
|
||||
return "$HOME/" + UserOverrideContainersConfig
|
||||
}
|
||||
return OverrideContainersConfig
|
||||
}
|
||||
|
||||
// ReadCustomConfig reads the custom config and only generates a config based on it
|
||||
// If the custom config file does not exists, function will return an empty config
|
||||
func ReadCustomConfig() (*Config, error) {
|
||||
path, err := customConfigFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newConfig := &Config{}
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
if err := readConfigFromFile(path, newConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Let's always initialize the farm list so it is never nil
|
||||
if newConfig.Farms.List == nil {
|
||||
newConfig.Farms.List = make(map[string][]string)
|
||||
}
|
||||
return newConfig, nil
|
||||
}
|
||||
|
||||
// Write writes the configuration to the default file
|
||||
func (c *Config) Write() error {
|
||||
var err error
|
||||
path, err := customConfigFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts := &ioutils.AtomicFileWriterOptions{ExplicitCommit: true}
|
||||
configFile, err := ioutils.NewAtomicFileWriterWithOpts(path, 0o644, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer configFile.Close()
|
||||
|
||||
enc := toml.NewEncoder(configFile)
|
||||
if err := enc.Encode(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If no errors commit the changes to the config file
|
||||
return configFile.Commit()
|
||||
}
|
||||
|
||||
// Reload clean the cached config and reloads the configuration from containers.conf files
|
||||
// This function is meant to be used for long-running processes that need to reload potential changes made to
|
||||
// the cached containers.conf files.
|
||||
|
16
vendor/github.com/containers/common/pkg/config/config_darwin.go
generated
vendored
16
vendor/github.com/containers/common/pkg/config/config_darwin.go
generated
vendored
@ -1,9 +1,5 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
// OverrideContainersConfig holds the default config path overridden by the root user
|
||||
OverrideContainersConfig = "/etc/" + _configPath
|
||||
@ -16,18 +12,6 @@ const (
|
||||
DefaultSignaturePolicyPath = "/etc/containers/policy.json"
|
||||
)
|
||||
|
||||
// podman remote clients on darwin cannot use unshare.isRootless() to determine the configuration file locations.
|
||||
func customConfigFile() (string, error) {
|
||||
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
|
||||
return path, nil
|
||||
}
|
||||
return rootlessConfigPath()
|
||||
}
|
||||
|
||||
func ifRootlessConfigPath() (string, error) {
|
||||
return rootlessConfigPath()
|
||||
}
|
||||
|
||||
var defaultHelperBinariesDir = []string{
|
||||
// Relative to the binary directory
|
||||
"$BINDIR/../libexec/podman",
|
||||
|
16
vendor/github.com/containers/common/pkg/config/config_freebsd.go
generated
vendored
16
vendor/github.com/containers/common/pkg/config/config_freebsd.go
generated
vendored
@ -1,9 +1,5 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
// OverrideContainersConfig holds the default config path overridden by the root user
|
||||
OverrideContainersConfig = "/usr/local/etc/" + _configPath
|
||||
@ -16,18 +12,6 @@ const (
|
||||
DefaultSignaturePolicyPath = "/usr/local/etc/containers/policy.json"
|
||||
)
|
||||
|
||||
// podman remote clients on freebsd cannot use unshare.isRootless() to determine the configuration file locations.
|
||||
func customConfigFile() (string, error) {
|
||||
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
|
||||
return path, nil
|
||||
}
|
||||
return rootlessConfigPath()
|
||||
}
|
||||
|
||||
func ifRootlessConfigPath() (string, error) {
|
||||
return rootlessConfigPath()
|
||||
}
|
||||
|
||||
var defaultHelperBinariesDir = []string{
|
||||
"/usr/local/bin",
|
||||
"/usr/local/libexec/podman",
|
||||
|
28
vendor/github.com/containers/common/pkg/config/config_linux.go
generated
vendored
28
vendor/github.com/containers/common/pkg/config/config_linux.go
generated
vendored
@ -1,9 +1,6 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/storage/pkg/unshare"
|
||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||
)
|
||||
|
||||
@ -23,31 +20,6 @@ func selinuxEnabled() bool {
|
||||
return selinux.GetEnabled()
|
||||
}
|
||||
|
||||
func customConfigFile() (string, error) {
|
||||
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
|
||||
return path, nil
|
||||
}
|
||||
if unshare.GetRootlessUID() > 0 {
|
||||
path, err := rootlessConfigPath()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
return OverrideContainersConfig, nil
|
||||
}
|
||||
|
||||
func ifRootlessConfigPath() (string, error) {
|
||||
if unshare.GetRootlessUID() > 0 {
|
||||
path, err := rootlessConfigPath()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var defaultHelperBinariesDir = []string{
|
||||
"/usr/local/libexec/podman",
|
||||
"/usr/local/lib/podman",
|
||||
|
25
vendor/github.com/containers/common/pkg/config/config_unix.go
generated
vendored
Normal file
25
vendor/github.com/containers/common/pkg/config/config_unix.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
//go:build !windows
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/storage/pkg/unshare"
|
||||
)
|
||||
|
||||
// userConfigPath returns the path to the users local config that is
|
||||
// not shared with other users. It uses $XDG_CONFIG_HOME/containers...
|
||||
// if set or $HOME/.config/containers... if not.
|
||||
func userConfigPath() (string, error) {
|
||||
if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
return filepath.Join(configHome, _configPath), nil
|
||||
}
|
||||
home, err := unshare.HomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filepath.Join(home, UserOverrideContainersConfig), nil
|
||||
}
|
12
vendor/github.com/containers/common/pkg/config/config_windows.go
generated
vendored
12
vendor/github.com/containers/common/pkg/config/config_windows.go
generated
vendored
@ -17,15 +17,9 @@ const (
|
||||
_typeBind = "bind"
|
||||
)
|
||||
|
||||
// podman remote clients on windows cannot use unshare.isRootless() to determine the configuration file locations.
|
||||
func customConfigFile() (string, error) {
|
||||
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
|
||||
return path, nil
|
||||
}
|
||||
return os.Getenv("APPDATA") + "\\containers\\containers.conf", nil
|
||||
}
|
||||
|
||||
func ifRootlessConfigPath() (string, error) {
|
||||
// userConfigPath returns the path to the users local config that is
|
||||
// not shared with other users. It uses $APPDATA/containers...
|
||||
func userConfigPath() (string, error) {
|
||||
return os.Getenv("APPDATA") + "\\containers\\containers.conf", nil
|
||||
}
|
||||
|
||||
|
286
vendor/github.com/containers/common/pkg/config/connections.go
generated
vendored
Normal file
286
vendor/github.com/containers/common/pkg/config/connections.go
generated
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
)
|
||||
|
||||
const connectionsFile = "podman-connections.conf"
|
||||
|
||||
// connectionsConfigFile returns the path to the rw connections config file
|
||||
func connectionsConfigFile() (string, error) {
|
||||
if path, found := os.LookupEnv("PODMAN_CONNECTIONS_CONF"); found {
|
||||
return path, nil
|
||||
}
|
||||
path, err := userConfigPath()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// file is stored next to containers.conf
|
||||
return filepath.Join(filepath.Dir(path), connectionsFile), nil
|
||||
}
|
||||
|
||||
type ConnectionConfig struct {
|
||||
Default string `json:",omitempty"`
|
||||
Connections map[string]Destination `json:",omitempty"`
|
||||
}
|
||||
|
||||
type ConnectionsFile struct {
|
||||
Connection ConnectionConfig `json:",omitempty"`
|
||||
Farm FarmConfig `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Connection struct {
|
||||
// Name of the connection
|
||||
Name string
|
||||
|
||||
// Destination for this connection
|
||||
Destination
|
||||
|
||||
// Default if this connection is the default
|
||||
Default bool
|
||||
|
||||
// ReadWrite if true the connection is stored in the connections file
|
||||
ReadWrite bool
|
||||
}
|
||||
|
||||
type Farm struct {
|
||||
// Name of the farm
|
||||
Name string
|
||||
|
||||
// Connections
|
||||
Connections []string
|
||||
|
||||
// Default if this is the default farm
|
||||
Default bool
|
||||
|
||||
// ReadWrite if true the farm is stored in the connections file
|
||||
ReadWrite bool
|
||||
}
|
||||
|
||||
func readConnectionConf() (*ConnectionsFile, string, error) {
|
||||
path, err := connectionsConfigFile()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
conf := new(ConnectionsFile)
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
// return empty config if file does not exists
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return conf, path, nil
|
||||
}
|
||||
|
||||
return nil, "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
err = json.NewDecoder(f).Decode(conf)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("parse %q: %w", path, err)
|
||||
}
|
||||
return conf, path, nil
|
||||
}
|
||||
|
||||
func writeConnectionConf(path string, conf *ConnectionsFile) error {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts := &ioutils.AtomicFileWriterOptions{ExplicitCommit: true}
|
||||
configFile, err := ioutils.NewAtomicFileWriterWithOpts(path, 0o644, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer configFile.Close()
|
||||
|
||||
err = json.NewEncoder(configFile).Encode(conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If no errors commit the changes to the config file
|
||||
return configFile.Commit()
|
||||
}
|
||||
|
||||
// EditConnectionConfig must be used to edit the connections config.
|
||||
// The function will read and write the file automatically and the
|
||||
// callback function just needs to modify the cfg as needed.
|
||||
func EditConnectionConfig(callback func(cfg *ConnectionsFile) error) error {
|
||||
conf, path, err := readConnectionConf()
|
||||
if err != nil {
|
||||
return fmt.Errorf("read connections file: %w", err)
|
||||
}
|
||||
if conf.Farm.List == nil {
|
||||
conf.Farm.List = make(map[string][]string)
|
||||
}
|
||||
|
||||
if err := callback(conf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeConnectionConf(path, conf)
|
||||
}
|
||||
|
||||
func makeConnection(name string, dst Destination, def, readWrite bool) *Connection {
|
||||
return &Connection{
|
||||
Name: name,
|
||||
Destination: dst,
|
||||
Default: def,
|
||||
ReadWrite: readWrite,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConnection return the connection for the given name or if def is set to true then return the default connection.
|
||||
func (c *Config) GetConnection(name string, def bool) (*Connection, error) {
|
||||
conConf, _, err := readConnectionConf()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defaultCon := conConf.Connection.Default
|
||||
if defaultCon == "" {
|
||||
defaultCon = c.Engine.ActiveService
|
||||
}
|
||||
if def {
|
||||
if defaultCon == "" {
|
||||
return nil, errors.New("no default connection found")
|
||||
}
|
||||
name = defaultCon
|
||||
} else {
|
||||
def = defaultCon == name
|
||||
}
|
||||
|
||||
if dst, ok := conConf.Connection.Connections[name]; ok {
|
||||
return makeConnection(name, dst, def, true), nil
|
||||
}
|
||||
if dst, ok := c.Engine.ServiceDestinations[name]; ok {
|
||||
return makeConnection(name, dst, def, false), nil
|
||||
}
|
||||
return nil, fmt.Errorf("connection %q not found", name)
|
||||
}
|
||||
|
||||
// GetAllConnections return all configured connections
|
||||
func (c *Config) GetAllConnections() ([]Connection, error) {
|
||||
conConf, _, err := readConnectionConf()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaultCon := conConf.Connection.Default
|
||||
if defaultCon == "" {
|
||||
defaultCon = c.Engine.ActiveService
|
||||
}
|
||||
|
||||
connections := make([]Connection, 0, len(conConf.Connection.Connections))
|
||||
for name, dst := range conConf.Connection.Connections {
|
||||
def := defaultCon == name
|
||||
connections = append(connections, *makeConnection(name, dst, def, true))
|
||||
}
|
||||
for name, dst := range c.Engine.ServiceDestinations {
|
||||
if _, ok := conConf.Connection.Connections[name]; ok {
|
||||
// connection name is overwritten by connections file
|
||||
continue
|
||||
}
|
||||
def := defaultCon == name
|
||||
connections = append(connections, *makeConnection(name, dst, def, false))
|
||||
}
|
||||
|
||||
return connections, nil
|
||||
}
|
||||
|
||||
func getConnections(cons []string, dests map[string]Destination) ([]Connection, error) {
|
||||
connections := make([]Connection, 0, len(cons))
|
||||
for _, name := range cons {
|
||||
if dst, ok := dests[name]; ok {
|
||||
connections = append(connections, *makeConnection(name, dst, false, false))
|
||||
} else {
|
||||
return nil, fmt.Errorf("connection %q not found", name)
|
||||
}
|
||||
}
|
||||
return connections, nil
|
||||
}
|
||||
|
||||
// GetFarmConnections return all the connections for the given farm.
|
||||
func (c *Config) GetFarmConnections(name string) ([]Connection, error) {
|
||||
_, cons, err := c.getFarmConnections(name, false)
|
||||
return cons, err
|
||||
}
|
||||
|
||||
// GetDefaultFarmConnections returns the name of the default farm
|
||||
// and the connections.
|
||||
func (c *Config) GetDefaultFarmConnections() (string, []Connection, error) {
|
||||
return c.getFarmConnections("", true)
|
||||
}
|
||||
|
||||
// getFarmConnections returns all connections for the given farm,
|
||||
// if def is true it will use the default farm instead of the name.
|
||||
// Returns the name of the farm and the connections for it.
|
||||
func (c *Config) getFarmConnections(name string, def bool) (string, []Connection, error) {
|
||||
conConf, _, err := readConnectionConf()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
defaultFarm := conConf.Farm.Default
|
||||
if defaultFarm == "" {
|
||||
defaultFarm = c.Farms.Default
|
||||
}
|
||||
if def {
|
||||
if defaultFarm == "" {
|
||||
return "", nil, errors.New("no default farm found")
|
||||
}
|
||||
name = defaultFarm
|
||||
}
|
||||
|
||||
if cons, ok := conConf.Farm.List[name]; ok {
|
||||
cons, err := getConnections(cons, conConf.Connection.Connections)
|
||||
return name, cons, err
|
||||
}
|
||||
if cons, ok := c.Farms.List[name]; ok {
|
||||
cons, err := getConnections(cons, c.Engine.ServiceDestinations)
|
||||
return name, cons, err
|
||||
}
|
||||
return "", nil, fmt.Errorf("farm %q not found", name)
|
||||
}
|
||||
|
||||
func makeFarm(name string, cons []string, def, readWrite bool) Farm {
|
||||
return Farm{
|
||||
Name: name,
|
||||
Connections: cons,
|
||||
Default: def,
|
||||
ReadWrite: readWrite,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllFarms returns all configured farms
|
||||
func (c *Config) GetAllFarms() ([]Farm, error) {
|
||||
conConf, _, err := readConnectionConf()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defaultFarm := conConf.Farm.Default
|
||||
if defaultFarm == "" {
|
||||
defaultFarm = c.Farms.Default
|
||||
}
|
||||
|
||||
farms := make([]Farm, 0, len(conConf.Farm.List))
|
||||
for name, cons := range conConf.Farm.List {
|
||||
def := defaultFarm == name
|
||||
farms = append(farms, makeFarm(name, cons, def, true))
|
||||
}
|
||||
for name, cons := range c.Farms.List {
|
||||
if _, ok := conConf.Farm.List[name]; ok {
|
||||
// farm name is overwritten by connections file
|
||||
continue
|
||||
}
|
||||
def := defaultFarm == name
|
||||
farms = append(farms, makeFarm(name, cons, def, false))
|
||||
}
|
||||
|
||||
return farms, nil
|
||||
}
|
3
vendor/github.com/containers/common/pkg/config/containers.conf
generated
vendored
3
vendor/github.com/containers/common/pkg/config/containers.conf
generated
vendored
@ -10,7 +10,8 @@
|
||||
# locations in the following order:
|
||||
# 1. /usr/share/containers/containers.conf
|
||||
# 2. /etc/containers/containers.conf
|
||||
# 3. $HOME/.config/containers/containers.conf (Rootless containers ONLY)
|
||||
# 3. $XDG_CONFIG_HOME/containers/containers.conf or
|
||||
# $HOME/.config/containers/containers.conf if $XDG_CONFIG_HOME is not set
|
||||
# Items specified in the latter containers.conf, if they exist, override the
|
||||
# previous containers.conf settings, or the default settings.
|
||||
|
||||
|
51
vendor/github.com/containers/common/pkg/config/new.go
generated
vendored
51
vendor/github.com/containers/common/pkg/config/new.go
generated
vendored
@ -21,7 +21,6 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
// FIXME: update code base and tests to use the two constants below.
|
||||
containersConfEnv = "CONTAINERS_CONF"
|
||||
containersConfOverrideEnv = containersConfEnv + "_OVERRIDE"
|
||||
)
|
||||
@ -79,15 +78,34 @@ func newLocked(options *Options) (*Config, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("finding config on system: %w", err)
|
||||
}
|
||||
// connectionsPath, err := connectionsConfigFile()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
for _, path := range configs {
|
||||
// var dests []*Destination
|
||||
// if path == connectionsPath {
|
||||
// // Store the dest pointers so we know after the load if there are new pointers
|
||||
// // the connection changed and thus is read write.
|
||||
// dests = maps.Values(config.Engine.ServiceDestinations)
|
||||
// }
|
||||
|
||||
// Merge changes in later configs with the previous configs.
|
||||
// Each config file that specified fields, will override the
|
||||
// previous fields.
|
||||
if err = readConfigFromFile(path, config); err != nil {
|
||||
if err = readConfigFromFile(path, config, true); err != nil {
|
||||
return nil, fmt.Errorf("reading system config %q: %w", path, err)
|
||||
}
|
||||
logrus.Debugf("Merged system config %q", path)
|
||||
logrus.Tracef("%+v", config)
|
||||
|
||||
// // if there is a new dest now we know it is read write as it was in the connections.conf file
|
||||
// for _, dest := range config.Engine.ServiceDestinations {
|
||||
// if !slices.Contains(dests, dest) {
|
||||
// dest.ReadWrite = true
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
modules, err := options.modules()
|
||||
@ -115,7 +133,7 @@ func newLocked(options *Options) (*Config, error) {
|
||||
}
|
||||
// readConfigFromFile reads in container config in the specified
|
||||
// file and then merge changes with the current default.
|
||||
if err := readConfigFromFile(add, config); err != nil {
|
||||
if err := readConfigFromFile(add, config, false); err != nil {
|
||||
return nil, fmt.Errorf("reading additional config %q: %w", add, err)
|
||||
}
|
||||
logrus.Debugf("Merged additional config %q", add)
|
||||
@ -157,12 +175,8 @@ func systemConfigs() (configs []string, finalErr error) {
|
||||
}
|
||||
return append(configs, path), nil
|
||||
}
|
||||
if _, err := os.Stat(DefaultContainersConfig); err == nil {
|
||||
configs = append(configs, DefaultContainersConfig)
|
||||
}
|
||||
if _, err := os.Stat(OverrideContainersConfig); err == nil {
|
||||
configs = append(configs, OverrideContainersConfig)
|
||||
}
|
||||
configs = append(configs, DefaultContainersConfig)
|
||||
configs = append(configs, OverrideContainersConfig)
|
||||
|
||||
var err error
|
||||
configs, err = addConfigs(OverrideContainersConfig+".d", configs)
|
||||
@ -170,18 +184,14 @@ func systemConfigs() (configs []string, finalErr error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path, err := ifRootlessConfigPath()
|
||||
path, err := userConfigPath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if path != "" {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
configs = append(configs, path)
|
||||
}
|
||||
configs, err = addConfigs(path+".d", configs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configs = append(configs, path)
|
||||
configs, err = addConfigs(path+".d", configs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return configs, nil
|
||||
}
|
||||
@ -225,10 +235,13 @@ func addConfigs(dirPath string, configs []string) ([]string, error) {
|
||||
// unmarshal its content into a Config. The config param specifies the previous
|
||||
// default config. If the path, only specifies a few fields in the Toml file
|
||||
// the defaults from the config parameter will be used for all other fields.
|
||||
func readConfigFromFile(path string, config *Config) error {
|
||||
func readConfigFromFile(path string, config *Config, ignoreErrNotExist bool) error {
|
||||
logrus.Tracef("Reading configuration file %q", path)
|
||||
meta, err := toml.DecodeFile(path, config)
|
||||
if err != nil {
|
||||
if ignoreErrNotExist && errors.Is(err, fs.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("decode configuration %v: %w", path, err)
|
||||
}
|
||||
keys := meta.Undecoded()
|
||||
|
106
vendor/github.com/containers/common/pkg/manifests/manifests.go
generated
vendored
106
vendor/github.com/containers/common/pkg/manifests/manifests.go
generated
vendored
@ -19,6 +19,7 @@ type List interface {
|
||||
Remove(instanceDigest digest.Digest) error
|
||||
SetURLs(instanceDigest digest.Digest, urls []string) error
|
||||
URLs(instanceDigest digest.Digest) ([]string, error)
|
||||
ClearAnnotations(instanceDigest *digest.Digest) error
|
||||
SetAnnotations(instanceDigest *digest.Digest, annotations map[string]string) error
|
||||
Annotations(instanceDigest *digest.Digest) (map[string]string, error)
|
||||
SetOS(instanceDigest digest.Digest, os string) error
|
||||
@ -100,18 +101,21 @@ func (l *list) AddInstance(manifestDigest digest.Digest, manifestSize int64, man
|
||||
Platform: schema2platform,
|
||||
})
|
||||
|
||||
ociv1platform := v1.Platform{
|
||||
ociv1platform := &v1.Platform{
|
||||
Architecture: architecture,
|
||||
OS: osName,
|
||||
OSVersion: osVersion,
|
||||
OSFeatures: osFeatures,
|
||||
Variant: variant,
|
||||
}
|
||||
if ociv1platform.Architecture == "" && ociv1platform.OS == "" && ociv1platform.OSVersion == "" && ociv1platform.Variant == "" && len(ociv1platform.OSFeatures) == 0 {
|
||||
ociv1platform = nil
|
||||
}
|
||||
l.oci.Manifests = append(l.oci.Manifests, v1.Descriptor{
|
||||
MediaType: manifestType,
|
||||
Size: manifestSize,
|
||||
Digest: manifestDigest,
|
||||
Platform: &ociv1platform,
|
||||
Platform: ociv1platform,
|
||||
})
|
||||
|
||||
return nil
|
||||
@ -170,7 +174,13 @@ func (l *list) SetURLs(instanceDigest digest.Digest, urls []string) error {
|
||||
return err
|
||||
}
|
||||
oci.URLs = append([]string{}, urls...)
|
||||
if len(oci.URLs) == 0 {
|
||||
oci.URLs = nil
|
||||
}
|
||||
docker.URLs = append([]string{}, urls...)
|
||||
if len(docker.URLs) == 0 {
|
||||
docker.URLs = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -183,7 +193,24 @@ func (l *list) URLs(instanceDigest digest.Digest) ([]string, error) {
|
||||
return append([]string{}, oci.URLs...), nil
|
||||
}
|
||||
|
||||
// SetAnnotations sets annotations on the image index, or on a specific manifest.
|
||||
// ClearAnnotations removes all annotations from the image index, or from a
|
||||
// specific manifest.
|
||||
// The field is specific to the OCI image index format, and is not present in Docker manifest lists.
|
||||
func (l *list) ClearAnnotations(instanceDigest *digest.Digest) error {
|
||||
a := &l.oci.Annotations
|
||||
if instanceDigest != nil {
|
||||
oci, err := l.findOCIv1(*instanceDigest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a = &oci.Annotations
|
||||
}
|
||||
*a = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAnnotations sets annotations on the image index, or on a specific
|
||||
// manifest.
|
||||
// The field is specific to the OCI image index format, and is not present in Docker manifest lists.
|
||||
func (l *list) SetAnnotations(instanceDigest *digest.Digest, annotations map[string]string) error {
|
||||
a := &l.oci.Annotations
|
||||
@ -194,10 +221,15 @@ func (l *list) SetAnnotations(instanceDigest *digest.Digest, annotations map[str
|
||||
}
|
||||
a = &oci.Annotations
|
||||
}
|
||||
(*a) = make(map[string]string)
|
||||
if *a == nil {
|
||||
(*a) = make(map[string]string)
|
||||
}
|
||||
for k, v := range annotations {
|
||||
(*a)[k] = v
|
||||
}
|
||||
if len(*a) == 0 {
|
||||
*a = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -230,7 +262,13 @@ func (l *list) SetOS(instanceDigest digest.Digest, os string) error {
|
||||
return err
|
||||
}
|
||||
docker.Platform.OS = os
|
||||
if oci.Platform == nil {
|
||||
oci.Platform = &v1.Platform{}
|
||||
}
|
||||
oci.Platform.OS = os
|
||||
if oci.Platform.Architecture == "" && oci.Platform.OS == "" && oci.Platform.OSVersion == "" && oci.Platform.Variant == "" && len(oci.Platform.OSFeatures) == 0 {
|
||||
oci.Platform = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -240,7 +278,11 @@ func (l *list) OS(instanceDigest digest.Digest) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return oci.Platform.OS, nil
|
||||
platform := oci.Platform
|
||||
if platform == nil {
|
||||
platform = &v1.Platform{}
|
||||
}
|
||||
return platform.OS, nil
|
||||
}
|
||||
|
||||
// SetArchitecture sets the Architecture field in the platform information associated with the instance with the specified digest.
|
||||
@ -254,7 +296,13 @@ func (l *list) SetArchitecture(instanceDigest digest.Digest, arch string) error
|
||||
return err
|
||||
}
|
||||
docker.Platform.Architecture = arch
|
||||
if oci.Platform == nil {
|
||||
oci.Platform = &v1.Platform{}
|
||||
}
|
||||
oci.Platform.Architecture = arch
|
||||
if oci.Platform.Architecture == "" && oci.Platform.OS == "" && oci.Platform.OSVersion == "" && oci.Platform.Variant == "" && len(oci.Platform.OSFeatures) == 0 {
|
||||
oci.Platform = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -264,7 +312,11 @@ func (l *list) Architecture(instanceDigest digest.Digest) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return oci.Platform.Architecture, nil
|
||||
platform := oci.Platform
|
||||
if platform == nil {
|
||||
platform = &v1.Platform{}
|
||||
}
|
||||
return platform.Architecture, nil
|
||||
}
|
||||
|
||||
// SetOSVersion sets the OSVersion field in the platform information associated with the instance with the specified digest.
|
||||
@ -278,7 +330,13 @@ func (l *list) SetOSVersion(instanceDigest digest.Digest, osVersion string) erro
|
||||
return err
|
||||
}
|
||||
docker.Platform.OSVersion = osVersion
|
||||
if oci.Platform == nil {
|
||||
oci.Platform = &v1.Platform{}
|
||||
}
|
||||
oci.Platform.OSVersion = osVersion
|
||||
if oci.Platform.Architecture == "" && oci.Platform.OS == "" && oci.Platform.OSVersion == "" && oci.Platform.Variant == "" && len(oci.Platform.OSFeatures) == 0 {
|
||||
oci.Platform = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -288,7 +346,11 @@ func (l *list) OSVersion(instanceDigest digest.Digest) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return oci.Platform.OSVersion, nil
|
||||
platform := oci.Platform
|
||||
if platform == nil {
|
||||
platform = &v1.Platform{}
|
||||
}
|
||||
return platform.OSVersion, nil
|
||||
}
|
||||
|
||||
// SetVariant sets the Variant field in the platform information associated with the instance with the specified digest.
|
||||
@ -302,7 +364,13 @@ func (l *list) SetVariant(instanceDigest digest.Digest, variant string) error {
|
||||
return err
|
||||
}
|
||||
docker.Platform.Variant = variant
|
||||
if oci.Platform == nil {
|
||||
oci.Platform = &v1.Platform{}
|
||||
}
|
||||
oci.Platform.Variant = variant
|
||||
if oci.Platform.Architecture == "" && oci.Platform.OS == "" && oci.Platform.OSVersion == "" && oci.Platform.Variant == "" && len(oci.Platform.OSFeatures) == 0 {
|
||||
oci.Platform = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -312,7 +380,11 @@ func (l *list) Variant(instanceDigest digest.Digest) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return oci.Platform.Variant, nil
|
||||
platform := oci.Platform
|
||||
if platform == nil {
|
||||
platform = &v1.Platform{}
|
||||
}
|
||||
return platform.Variant, nil
|
||||
}
|
||||
|
||||
// SetFeatures sets the features list in the platform information associated with the instance with the specified digest.
|
||||
@ -323,6 +395,9 @@ func (l *list) SetFeatures(instanceDigest digest.Digest, features []string) erro
|
||||
return err
|
||||
}
|
||||
docker.Platform.Features = append([]string{}, features...)
|
||||
if len(docker.Platform.Features) == 0 {
|
||||
docker.Platform.Features = nil
|
||||
}
|
||||
// no OCI equivalent
|
||||
return nil
|
||||
}
|
||||
@ -348,7 +423,16 @@ func (l *list) SetOSFeatures(instanceDigest digest.Digest, osFeatures []string)
|
||||
return err
|
||||
}
|
||||
docker.Platform.OSFeatures = append([]string{}, osFeatures...)
|
||||
if oci.Platform == nil {
|
||||
oci.Platform = &v1.Platform{}
|
||||
}
|
||||
oci.Platform.OSFeatures = append([]string{}, osFeatures...)
|
||||
if len(oci.Platform.OSFeatures) == 0 {
|
||||
oci.Platform.OSFeatures = nil
|
||||
}
|
||||
if oci.Platform.Architecture == "" && oci.Platform.OS == "" && oci.Platform.OSVersion == "" && oci.Platform.Variant == "" && len(oci.Platform.OSFeatures) == 0 {
|
||||
oci.Platform = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -358,7 +442,11 @@ func (l *list) OSFeatures(instanceDigest digest.Digest) ([]string, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append([]string{}, oci.Platform.OSFeatures...), nil
|
||||
platform := oci.Platform
|
||||
if platform == nil {
|
||||
platform = &v1.Platform{}
|
||||
}
|
||||
return append([]string{}, platform.OSFeatures...), nil
|
||||
}
|
||||
|
||||
// SetMediaType sets the MediaType field in the instance with the specified digest.
|
||||
|
46
vendor/github.com/containers/common/pkg/ssh/connection_golang.go
generated
vendored
46
vendor/github.com/containers/common/pkg/ssh/connection_golang.go
generated
vendored
@ -53,32 +53,32 @@ func golangConnectionCreate(options ConnectionCreateOptions) error {
|
||||
dst.URI += uri.Path
|
||||
}
|
||||
|
||||
cfg, err := config.ReadCustomConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cfg.Engine.ServiceDestinations == nil {
|
||||
cfg.Engine.ServiceDestinations = map[string]config.Destination{
|
||||
options.Name: *dst,
|
||||
}
|
||||
cfg.Engine.ActiveService = options.Name
|
||||
} else {
|
||||
cfg.Engine.ServiceDestinations[options.Name] = *dst
|
||||
}
|
||||
|
||||
// Create or update an existing farm with the connection being added
|
||||
if options.Farm != "" {
|
||||
if len(cfg.Farms.List) == 0 {
|
||||
cfg.Farms.Default = options.Farm
|
||||
}
|
||||
if val, ok := cfg.Farms.List[options.Farm]; ok {
|
||||
cfg.Farms.List[options.Farm] = append(val, options.Name)
|
||||
// TODO this really should not live here, it must be in podman where we write the other connections as well.
|
||||
// This duplicates the code for no reason and I have a really hard time to make any sense of why this code
|
||||
// was added in the first place.
|
||||
return config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error {
|
||||
if cfg.Connection.Connections == nil {
|
||||
cfg.Connection.Connections = map[string]config.Destination{
|
||||
options.Name: *dst,
|
||||
}
|
||||
cfg.Connection.Default = options.Name
|
||||
} else {
|
||||
cfg.Farms.List[options.Farm] = []string{options.Name}
|
||||
cfg.Connection.Connections[options.Name] = *dst
|
||||
}
|
||||
}
|
||||
|
||||
return cfg.Write()
|
||||
// Create or update an existing farm with the connection being added
|
||||
if options.Farm != "" {
|
||||
if len(cfg.Farm.List) == 0 {
|
||||
cfg.Farm.Default = options.Farm
|
||||
}
|
||||
if val, ok := cfg.Farm.List[options.Farm]; ok {
|
||||
cfg.Farm.List[options.Farm] = append(val, options.Name)
|
||||
} else {
|
||||
cfg.Farm.List[options.Farm] = []string{options.Name}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func golangConnectionDial(options ConnectionDialOptions) (*ConnectionDialReport, error) {
|
||||
|
40
vendor/github.com/containers/common/pkg/ssh/connection_native.go
generated
vendored
40
vendor/github.com/containers/common/pkg/ssh/connection_native.go
generated
vendored
@ -72,24 +72,32 @@ func nativeConnectionCreate(options ConnectionCreateOptions) error {
|
||||
return fmt.Errorf("remote podman %q failed to report its UDS socket", uri.Host)
|
||||
}
|
||||
|
||||
cfg, err := config.ReadCustomConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if options.Default {
|
||||
cfg.Engine.ActiveService = options.Name
|
||||
}
|
||||
|
||||
if cfg.Engine.ServiceDestinations == nil {
|
||||
cfg.Engine.ServiceDestinations = map[string]config.Destination{
|
||||
options.Name: *dst,
|
||||
// TODO this really should not live here, it must be in podman where we write the other connections as well.
|
||||
// This duplicates the code for no reason and I have a really hard time to make any sense of why this code
|
||||
// was added in the first place.
|
||||
return config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error {
|
||||
if cfg.Connection.Connections == nil {
|
||||
cfg.Connection.Connections = map[string]config.Destination{
|
||||
options.Name: *dst,
|
||||
}
|
||||
cfg.Connection.Default = options.Name
|
||||
} else {
|
||||
cfg.Connection.Connections[options.Name] = *dst
|
||||
}
|
||||
cfg.Engine.ActiveService = options.Name
|
||||
} else {
|
||||
cfg.Engine.ServiceDestinations[options.Name] = *dst
|
||||
}
|
||||
|
||||
return cfg.Write()
|
||||
// Create or update an existing farm with the connection being added
|
||||
if options.Farm != "" {
|
||||
if len(cfg.Farm.List) == 0 {
|
||||
cfg.Farm.Default = options.Farm
|
||||
}
|
||||
if val, ok := cfg.Farm.List[options.Farm]; ok {
|
||||
cfg.Farm.List[options.Farm] = append(val, options.Name)
|
||||
} else {
|
||||
cfg.Farm.List[options.Farm] = []string{options.Name}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func nativeConnectionExec(options ConnectionExecOptions) (*ConnectionExecReport, error) {
|
||||
|
Reference in New Issue
Block a user