mirror of
https://github.com/containers/podman.git
synced 2026-07-20 12:12:09 -04:00
Merge pull request #8298 from mheon/db_network_connect
Add support for network connect / disconnect to DB
This commit is contained in:
@@ -94,7 +94,6 @@ func NewBoltState(path string, runtime *Runtime) (State, error) {
|
||||
volBkt,
|
||||
allVolsBkt,
|
||||
execBkt,
|
||||
aliasesBkt,
|
||||
runtimeConfigBkt,
|
||||
}
|
||||
|
||||
@@ -972,6 +971,58 @@ func (s *BoltState) AllContainers() ([]*Container, error) {
|
||||
return ctrs, nil
|
||||
}
|
||||
|
||||
// GetNetworks returns the CNI networks this container is a part of.
|
||||
func (s *BoltState) GetNetworks(ctr *Container) ([]string, error) {
|
||||
if !s.valid {
|
||||
return nil, define.ErrDBClosed
|
||||
}
|
||||
|
||||
if !ctr.valid {
|
||||
return nil, define.ErrCtrRemoved
|
||||
}
|
||||
|
||||
if s.namespace != "" && s.namespace != ctr.config.Namespace {
|
||||
return nil, errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
|
||||
}
|
||||
|
||||
ctrID := []byte(ctr.ID())
|
||||
|
||||
db, err := s.getDBCon()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer s.deferredCloseDBCon(db)
|
||||
|
||||
networks := []string{}
|
||||
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
ctrBucket, err := getCtrBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbCtr := ctrBucket.Bucket(ctrID)
|
||||
if dbCtr == nil {
|
||||
ctr.valid = false
|
||||
return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
|
||||
}
|
||||
|
||||
ctrNetworkBkt := dbCtr.Bucket(networksBkt)
|
||||
if ctrNetworkBkt == nil {
|
||||
return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not joined to any CNI networks", ctr.ID())
|
||||
}
|
||||
|
||||
return ctrNetworkBkt.ForEach(func(network, v []byte) error {
|
||||
networks = append(networks, string(network))
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return networks, nil
|
||||
}
|
||||
|
||||
// GetNetworkAliases retrieves the network aliases for the given container in
|
||||
// the given CNI network.
|
||||
func (s *BoltState) GetNetworkAliases(ctr *Container, network string) ([]string, error) {
|
||||
@@ -1032,7 +1083,8 @@ func (s *BoltState) GetNetworkAliases(ctr *Container, network string) ([]string,
|
||||
|
||||
netAliasesBkt := ctrAliasesBkt.Bucket([]byte(network))
|
||||
if netAliasesBkt == nil {
|
||||
return errors.Wrapf(define.ErrNoAliasesForNetwork, "container %s has no aliases for network %q", ctr.ID(), network)
|
||||
// No aliases for this specific network.
|
||||
return nil
|
||||
}
|
||||
|
||||
return netAliasesBkt.ForEach(func(alias, v []byte) error {
|
||||
@@ -1120,10 +1172,9 @@ func (s *BoltState) GetAllNetworkAliases(ctr *Container) (map[string][]string, e
|
||||
return aliases, nil
|
||||
}
|
||||
|
||||
// SetNetworkAliases sets network aliases for the given container in the given
|
||||
// network. All existing aliases for that network (if any exist) will be removed,
|
||||
// to be replaced by the new aliases given.
|
||||
func (s *BoltState) SetNetworkAliases(ctr *Container, network string, aliases []string) error {
|
||||
// NetworkConnect adds the given container to the given network. If aliases are
|
||||
// specified, those will be added to the given network.
|
||||
func (s *BoltState) NetworkConnect(ctr *Container, network string, aliases []string) error {
|
||||
if !s.valid {
|
||||
return define.ErrDBClosed
|
||||
}
|
||||
@@ -1154,278 +1205,124 @@ func (s *BoltState) SetNetworkAliases(ctr *Container, network string, aliases []
|
||||
return err
|
||||
}
|
||||
|
||||
allAliasesBucket, err := getAliasesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
netAllAliasesBucket, err := allAliasesBucket.CreateBucketIfNotExists([]byte(network))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating network aliases bucket for network %s", network)
|
||||
}
|
||||
|
||||
dbCtr := ctrBucket.Bucket(ctrID)
|
||||
if dbCtr == nil {
|
||||
ctr.valid = false
|
||||
return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
|
||||
}
|
||||
|
||||
ctrAliasesBkt := dbCtr.Bucket(aliasesBkt)
|
||||
if ctrAliasesBkt == nil {
|
||||
return errors.Wrapf(define.ErrNoAliases, "container %s has no network aliases", ctr.ID())
|
||||
ctrAliasesBkt, err := dbCtr.CreateBucketIfNotExists(aliasesBkt)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating aliases bucket for container %s", ctr.ID())
|
||||
}
|
||||
|
||||
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
|
||||
if ctrNetworksBkt == nil {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s is not connected to any CNI networks, so cannot add aliases", ctr.ID())
|
||||
}
|
||||
netConnected := ctrNetworksBkt.Get([]byte(network))
|
||||
if netConnected == nil {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s is not connected to CNI network %q, so cannot add aliases for this network", ctr.ID(), network)
|
||||
}
|
||||
|
||||
namesBucket, err := getNamesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the container already has network aliases for this network.
|
||||
netAliasesBkt := ctrAliasesBkt.Bucket([]byte(network))
|
||||
if netAliasesBkt != nil {
|
||||
// We have aliases. Have to remove them.
|
||||
forEachErr := netAliasesBkt.ForEach(func(alias, v []byte) error {
|
||||
// Relies on errors.Wrapf(nil, ...) returning
|
||||
// nil.
|
||||
return errors.Wrapf(netAllAliasesBucket.Delete(alias), "error removing alias %q from network %q when changing aliases for container %s", string(alias), network, ctr.ID())
|
||||
})
|
||||
if forEachErr != nil {
|
||||
return forEachErr
|
||||
}
|
||||
}
|
||||
|
||||
if netAliasesBkt == nil {
|
||||
newBkt, err := ctrAliasesBkt.CreateBucket([]byte(network))
|
||||
ctrNetworksBkt, err = dbCtr.CreateBucket(networksBkt)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create bucket for network aliases for network %q", network)
|
||||
return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID())
|
||||
}
|
||||
netAliasesBkt = newBkt
|
||||
}
|
||||
|
||||
for _, alias := range aliases {
|
||||
// Check if safe to use
|
||||
aliasExists := netAllAliasesBucket.Get([]byte(alias))
|
||||
if aliasExists != nil {
|
||||
return errors.Wrapf(define.ErrAliasExists, "network alias %q already exists in network %q (used by container %s)", alias, network, string(aliasExists))
|
||||
ctrNetworks := ctr.config.Networks
|
||||
if len(ctrNetworks) == 0 {
|
||||
ctrNetworks = []string{ctr.runtime.netPlugin.GetDefaultNetworkName()}
|
||||
}
|
||||
nameExists := namesBucket.Get([]byte(alias))
|
||||
if nameExists != nil {
|
||||
return errors.Wrapf(define.ErrCtrExists, "a container or pod already uses the name %q, cannot add network alias for container %s", alias, ctr.ID())
|
||||
}
|
||||
|
||||
// Add alias
|
||||
if err := netAliasesBkt.Put([]byte(alias), ctrID); err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s network %q alias %q to DB", ctr.ID(), network, alias)
|
||||
}
|
||||
if err := netAllAliasesBucket.Put([]byte(alias), ctrID); err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s network %q alias %q to all aliases in DB", ctr.ID(), network, alias)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveNetworkAliases removes network aliases of the given container in the
|
||||
// given network.
|
||||
func (s *BoltState) RemoveNetworkAliases(ctr *Container, network string) error {
|
||||
if !s.valid {
|
||||
return define.ErrDBClosed
|
||||
}
|
||||
|
||||
if !ctr.valid {
|
||||
return define.ErrCtrRemoved
|
||||
}
|
||||
|
||||
if network == "" {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
|
||||
}
|
||||
|
||||
if s.namespace != "" && s.namespace != ctr.config.Namespace {
|
||||
return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
|
||||
}
|
||||
|
||||
ctrID := []byte(ctr.ID())
|
||||
|
||||
db, err := s.getDBCon()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.deferredCloseDBCon(db)
|
||||
|
||||
return db.Update(func(tx *bolt.Tx) error {
|
||||
ctrBucket, err := getCtrBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allAliasesBucket, err := getAliasesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
netAllAliasesBucket, err := allAliasesBucket.CreateBucketIfNotExists([]byte(network))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating network aliases bucket for network %s", network)
|
||||
}
|
||||
|
||||
dbCtr := ctrBucket.Bucket(ctrID)
|
||||
if dbCtr == nil {
|
||||
ctr.valid = false
|
||||
return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
|
||||
}
|
||||
|
||||
ctrAliasesBkt := dbCtr.Bucket(aliasesBkt)
|
||||
if ctrAliasesBkt == nil {
|
||||
return errors.Wrapf(define.ErrNoAliases, "container %s has no network aliases", ctr.ID())
|
||||
}
|
||||
|
||||
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
|
||||
if ctrNetworksBkt == nil {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s is not connected to any CNI networks, so cannot add aliases", ctr.ID())
|
||||
}
|
||||
netConnected := ctrNetworksBkt.Get([]byte(network))
|
||||
if netConnected == nil {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s is not connected to CNI network %q, so cannot add aliases for this network", ctr.ID(), network)
|
||||
}
|
||||
|
||||
// Check if the container already has network aliases for this network.
|
||||
netAliasesBkt := ctrAliasesBkt.Bucket([]byte(network))
|
||||
if netAliasesBkt != nil {
|
||||
// We have aliases. Remove them.
|
||||
forEachErr := netAliasesBkt.ForEach(func(alias, v []byte) error {
|
||||
// Relies on errors.Wrapf(nil, ...) returning
|
||||
// nil.
|
||||
return errors.Wrapf(netAllAliasesBucket.Delete(alias), "error removing alias %q from network %q when changing aliases for container %s", string(alias), network, ctr.ID())
|
||||
})
|
||||
if forEachErr != nil {
|
||||
return forEachErr
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Get all network aliases for a single CNI network. Returns a map of alias to
|
||||
// container ID.
|
||||
func (s *BoltState) GetAllAliasesForNetwork(network string) (map[string]string, error) {
|
||||
if !s.valid {
|
||||
return nil, define.ErrDBClosed
|
||||
}
|
||||
|
||||
if network == "" {
|
||||
return nil, errors.Wrapf(define.ErrInvalidArg, "network name must not be empty")
|
||||
}
|
||||
|
||||
db, err := s.getDBCon()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer s.deferredCloseDBCon(db)
|
||||
|
||||
aliases := make(map[string]string)
|
||||
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
aliasBucket, err := getAliasesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbAlias := aliasBucket.Bucket([]byte(network))
|
||||
if dbAlias == nil {
|
||||
// We can't tell if the network exists, or doesn't exist
|
||||
// So... Assume it exists, but has no aliases.
|
||||
return nil
|
||||
}
|
||||
|
||||
return dbAlias.ForEach(func(alias, ctrId []byte) error {
|
||||
aliases[string(alias)] = string(ctrId)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return aliases, nil
|
||||
}
|
||||
|
||||
// RemoveAllAliasesForNetwork removes all the aliases in a given CNI network, as
|
||||
// part of that network being removed.
|
||||
func (s *BoltState) RemoveAllAliasesForNetwork(network string) error {
|
||||
if !s.valid {
|
||||
return define.ErrDBClosed
|
||||
}
|
||||
|
||||
if network == "" {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
|
||||
}
|
||||
|
||||
db, err := s.getDBCon()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.deferredCloseDBCon(db)
|
||||
|
||||
return db.Update(func(tx *bolt.Tx) error {
|
||||
allCtrsBucket, err := getAllCtrsBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctrBucket, err := getCtrBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allAliasesBucket, err := getAliasesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkAliasesBucketExists := allAliasesBucket.Bucket([]byte(network))
|
||||
if checkAliasesBucketExists != nil {
|
||||
if err := allAliasesBucket.DeleteBucket([]byte(network)); err != nil {
|
||||
return errors.Wrapf(err, "error removing network %s aliases bucket from DB", network)
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through all containers and remove their aliases
|
||||
// bucket for the network.
|
||||
return allCtrsBucket.ForEach(func(ctrID, ctrName []byte) error {
|
||||
dbCtr := ctrBucket.Bucket(ctrID)
|
||||
if dbCtr == nil {
|
||||
// DB State is inconsistent... but we can't do
|
||||
// anything about it.
|
||||
// Log and move on.
|
||||
logrus.Errorf("Container %s listed in all containers, but has no bucket!", string(ctrID))
|
||||
return nil
|
||||
}
|
||||
|
||||
dbCtrAliases := dbCtr.Bucket(aliasesBkt)
|
||||
if dbCtrAliases == nil {
|
||||
// Container has no aliases, this is OK.
|
||||
return nil
|
||||
}
|
||||
|
||||
ctrNetAliases := dbCtrAliases.Bucket([]byte(network))
|
||||
if ctrNetAliases != nil {
|
||||
if err := dbCtrAliases.DeleteBucket([]byte(network)); err != nil {
|
||||
return errors.Wrapf(err, "error removing bucket for network aliases for network %s from container %s", network, string(ctrID))
|
||||
// Copy in all the container's CNI networks
|
||||
for _, net := range ctrNetworks {
|
||||
if err := ctrNetworksBkt.Put([]byte(net), ctrID); err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s network %s to DB", ctr.ID(), net)
|
||||
}
|
||||
}
|
||||
}
|
||||
netConnected := ctrNetworksBkt.Get([]byte(network))
|
||||
if netConnected != nil {
|
||||
return errors.Wrapf(define.ErrNetworkExists, "container %s is already connected to CNI network %q", ctr.ID(), network)
|
||||
}
|
||||
|
||||
// Add the network
|
||||
if err := ctrNetworksBkt.Put([]byte(network), ctrID); err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s to network %s in DB", ctr.ID(), network)
|
||||
}
|
||||
|
||||
ctrNetAliasesBkt, err := ctrAliasesBkt.CreateBucketIfNotExists([]byte(network))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s network aliases bucket for network %s", ctr.ID(), network)
|
||||
}
|
||||
for _, alias := range aliases {
|
||||
if err := ctrNetAliasesBkt.Put([]byte(alias), ctrID); err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s network alias %s for network %s", ctr.ID(), alias, network)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// NetworkDisconnect disconnects the container from the given network, also
|
||||
// removing any aliases in the network.
|
||||
func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error {
|
||||
if !s.valid {
|
||||
return define.ErrDBClosed
|
||||
}
|
||||
|
||||
if !ctr.valid {
|
||||
return define.ErrCtrRemoved
|
||||
}
|
||||
|
||||
if network == "" {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
|
||||
}
|
||||
|
||||
if s.namespace != "" && s.namespace != ctr.config.Namespace {
|
||||
return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
|
||||
}
|
||||
|
||||
ctrID := []byte(ctr.ID())
|
||||
|
||||
db, err := s.getDBCon()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.deferredCloseDBCon(db)
|
||||
|
||||
return db.Update(func(tx *bolt.Tx) error {
|
||||
ctrBucket, err := getCtrBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbCtr := ctrBucket.Bucket(ctrID)
|
||||
if dbCtr == nil {
|
||||
ctr.valid = false
|
||||
return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
|
||||
}
|
||||
|
||||
ctrAliasesBkt := dbCtr.Bucket(aliasesBkt)
|
||||
if ctrAliasesBkt == nil {
|
||||
return errors.Wrapf(define.ErrNoAliases, "container %s has no network aliases", ctr.ID())
|
||||
}
|
||||
|
||||
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
|
||||
if ctrNetworksBkt == nil {
|
||||
return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to any CNI networks, so cannot disconnect", ctr.ID())
|
||||
}
|
||||
netConnected := ctrNetworksBkt.Get([]byte(network))
|
||||
if netConnected == nil {
|
||||
return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to CNI network %q", ctr.ID(), network)
|
||||
}
|
||||
|
||||
if err := ctrNetworksBkt.Delete([]byte(network)); err != nil {
|
||||
return errors.Wrapf(err, "error removing container %s from network %s", ctr.ID(), network)
|
||||
}
|
||||
|
||||
bktExists := ctrAliasesBkt.Bucket([]byte(network))
|
||||
if bktExists == nil {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := ctrAliasesBkt.DeleteBucket([]byte(network)); err != nil {
|
||||
return errors.Wrapf(err, "error removing container %s network aliases for network %s", ctr.ID(), network)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -354,14 +354,6 @@ func getExecBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
||||
return bkt, nil
|
||||
}
|
||||
|
||||
func getAliasesBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
||||
bkt := tx.Bucket(aliasesBkt)
|
||||
if bkt == nil {
|
||||
return nil, errors.Wrapf(define.ErrDBBadConfig, "aliases bucket not found in DB")
|
||||
}
|
||||
return bkt, nil
|
||||
}
|
||||
|
||||
func getRuntimeConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
||||
bkt := tx.Bucket(runtimeConfigBkt)
|
||||
if bkt == nil {
|
||||
@@ -584,11 +576,6 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
|
||||
return err
|
||||
}
|
||||
|
||||
allAliasesBkt, err := getAliasesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If a pod was given, check if it exists
|
||||
var podDB *bolt.Bucket
|
||||
var podCtrs *bolt.Bucket
|
||||
@@ -635,41 +622,20 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
|
||||
return errors.Wrapf(err, "name \"%s\" is in use", ctr.Name())
|
||||
}
|
||||
|
||||
allNets := make(map[string]bool)
|
||||
|
||||
// Check that we don't have any empty network names
|
||||
for _, net := range ctr.config.Networks {
|
||||
if net == "" {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "network names cannot be an empty string")
|
||||
}
|
||||
allNets[net] = true
|
||||
}
|
||||
|
||||
// If we have network aliases, check if they are already in use.
|
||||
for net, aliases := range ctr.config.NetworkAliases {
|
||||
// Aliases cannot conflict with container names.
|
||||
for _, alias := range aliases {
|
||||
aliasExist := namesBucket.Get([]byte(alias))
|
||||
if aliasExist != nil {
|
||||
return errors.Wrapf(define.ErrCtrExists, "alias %q conflicts with existing container/pod name", alias)
|
||||
}
|
||||
}
|
||||
|
||||
netAliasesBkt := allAliasesBkt.Bucket([]byte(net))
|
||||
if netAliasesBkt != nil {
|
||||
for _, alias := range aliases {
|
||||
aliasExist := netAliasesBkt.Get([]byte(alias))
|
||||
if aliasExist != nil {
|
||||
return errors.Wrapf(define.ErrAliasExists, "network alias %q already exists for network %q", net, alias)
|
||||
}
|
||||
}
|
||||
}
|
||||
hasNet := false
|
||||
for _, testNet := range ctr.config.Networks {
|
||||
if testNet == net {
|
||||
hasNet = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasNet {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s has network aliases for network %q but is not part of that network", ctr.ID(), net)
|
||||
// Each network we have aliases for, must exist in networks
|
||||
for net := range ctr.config.NetworkAliases {
|
||||
if !allNets[net] {
|
||||
return errors.Wrapf(define.ErrNoSuchNetwork, "container %s has network aliases for network %q but is not part of that network", ctr.ID(), net)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,63 +656,6 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
|
||||
return errors.Wrapf(err, "error adding container %s to all containers bucket in DB", ctr.ID())
|
||||
}
|
||||
|
||||
// Check aliases for all networks, remove conflicts with the
|
||||
// container name.
|
||||
for _, net := range ctr.config.Networks {
|
||||
netAliasesBkt := allAliasesBkt.Bucket([]byte(net))
|
||||
if netAliasesBkt == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
otherCtrID := netAliasesBkt.Get(ctrName)
|
||||
if otherCtrID == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := netAliasesBkt.Delete(ctrName); err != nil {
|
||||
return errors.Wrapf(err, "error removing container %s name from network aliases for network %s", ctr.ID(), net)
|
||||
}
|
||||
|
||||
// We now need to remove from the other container.
|
||||
// To do this, we work through the container bucket,
|
||||
// then its aliases bucket, then its aliases for this
|
||||
// specific network, then we remove the alias.
|
||||
// Just slightly ridiculous. Just slightly.
|
||||
otherCtr := ctrBucket.Bucket(otherCtrID)
|
||||
if otherCtr == nil {
|
||||
// The state is inconsistent, but we can't do
|
||||
// much...
|
||||
logrus.Errorf("Container %s referred to by network alias but not present in state", string(otherCtrID))
|
||||
continue
|
||||
}
|
||||
otherCtrAliases := otherCtr.Bucket(aliasesBkt)
|
||||
if otherCtrAliases == nil {
|
||||
logrus.Errorf("Container %s is missing aliases but but has an alias", string(otherCtrID))
|
||||
continue
|
||||
}
|
||||
otherCtrNetworkAliases := otherCtrAliases.Bucket([]byte(net))
|
||||
if otherCtrNetworkAliases == nil {
|
||||
logrus.Errorf("Container %s is missing network aliases bucket for network %s but has alias in that network", string(otherCtrID), net)
|
||||
}
|
||||
if otherCtrNetworkAliases.Get(ctrName) != nil {
|
||||
if err := otherCtrNetworkAliases.Delete(ctrName); err != nil {
|
||||
return errors.Wrapf(err, "error removing container %s name from network %s aliases of container %s", ctr.Name(), net, string(otherCtrID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for net, aliases := range ctr.config.NetworkAliases {
|
||||
netAliasesBkt, err := allAliasesBkt.CreateBucketIfNotExists([]byte(net))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating network aliases bucket for network %q", net)
|
||||
}
|
||||
for _, alias := range aliases {
|
||||
if err := netAliasesBkt.Put([]byte(alias), ctrID); err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s network alias %q to network %q", ctr.ID(), alias, net)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newCtrBkt, err := ctrBucket.CreateBucket(ctrID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error adding container %s bucket to DB", ctr.ID())
|
||||
@@ -998,49 +907,6 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error
|
||||
return errors.Wrapf(define.ErrCtrExists, "container %s is a dependency of the following containers: %s", ctr.ID(), strings.Join(deps, ", "))
|
||||
}
|
||||
|
||||
// Does the container have any network aliases?
|
||||
ctrNetAliasesBkt := ctrExists.Bucket(aliasesBkt)
|
||||
if ctrNetAliasesBkt != nil {
|
||||
allAliasesBkt, err := getAliasesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctrNetworksBkt := ctrExists.Bucket(networksBkt)
|
||||
// Internal state mismatch if this doesn't exist - we'll just
|
||||
// assume there are no aliases in that case.
|
||||
if ctrNetworksBkt != nil {
|
||||
// This is a little gross. Iterate through all networks
|
||||
// the container is joined to. Check if we have aliases
|
||||
// for them. If we do have such aliases, remove all of
|
||||
// then from the global aliases table for that network.
|
||||
err = ctrNetworksBkt.ForEach(func(network, v []byte) error {
|
||||
netAliasesBkt := ctrNetAliasesBkt.Bucket(network)
|
||||
if netAliasesBkt == nil {
|
||||
return nil
|
||||
}
|
||||
netAllAliasesBkt := allAliasesBkt.Bucket(network)
|
||||
if netAllAliasesBkt == nil {
|
||||
// Again the state is inconsistent here,
|
||||
// but the best we can do is try and
|
||||
// recover by ignoring it.
|
||||
return nil
|
||||
}
|
||||
return netAliasesBkt.ForEach(func(alias, v []byte) error {
|
||||
// We don't want to hard-fail on a
|
||||
// missing alias, so continue if we hit
|
||||
// errors.
|
||||
if err := netAllAliasesBkt.Delete(alias); err != nil {
|
||||
logrus.Errorf("Error removing alias %q from network %q when removing container %s", string(alias), string(network), ctr.ID())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := ctrBucket.DeleteBucket(ctrID); err != nil {
|
||||
return errors.Wrapf(define.ErrInternal, "error deleting container %s from DB", ctr.ID())
|
||||
}
|
||||
|
||||
@@ -1085,3 +1085,31 @@ func (c *Container) Timezone() string {
|
||||
func (c *Container) Umask() string {
|
||||
return c.config.Umask
|
||||
}
|
||||
|
||||
// Networks gets all the networks this container is connected to.
|
||||
// Please do NOT use ctr.config.Networks, as this can be changed from those
|
||||
// values at runtime via network connect and disconnect.
|
||||
// If the container is configured to use CNI and this function returns an empty
|
||||
// array, the container will still be connected to the default network.
|
||||
func (c *Container) Networks() ([]string, error) {
|
||||
if !c.batched {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
if err := c.syncContainer(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return c.networks()
|
||||
}
|
||||
|
||||
// Unlocked accessor for networks
|
||||
func (c *Container) networks() ([]string, error) {
|
||||
networks, err := c.runtime.state.GetNetworks(c)
|
||||
if err != nil && errors.Cause(err) == define.ErrNoSuchNetwork {
|
||||
return c.config.Networks, nil
|
||||
}
|
||||
|
||||
return networks, err
|
||||
}
|
||||
|
||||
@@ -236,6 +236,9 @@ type ContainerNetworkConfig struct {
|
||||
// Will be appended to host's host file
|
||||
HostAdd []string `json:"hostsAdd,omitempty"`
|
||||
// Network names (CNI) to add container to. Empty to use default network.
|
||||
// Please note that these can be altered at runtime. The actual list is
|
||||
// stored in the DB and should be retrieved from there; this is only the
|
||||
// set of networks the container was *created* with.
|
||||
Networks []string `json:"networks,omitempty"`
|
||||
// Network mode specified for the default network.
|
||||
NetMode namespaces.NetworkMode `json:"networkMode,omitempty"`
|
||||
|
||||
@@ -641,12 +641,17 @@ func (c *Container) removeIPv4Allocations() error {
|
||||
cniDefaultNetwork = c.runtime.netPlugin.GetDefaultNetworkName()
|
||||
}
|
||||
|
||||
networks, err := c.networks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case len(c.config.Networks) > 0 && len(c.config.Networks) != len(c.state.NetworkStatus):
|
||||
return errors.Wrapf(define.ErrInternal, "network mismatch: asked to join %d CNI networks but got %d CNI results", len(c.config.Networks), len(c.state.NetworkStatus))
|
||||
case len(c.config.Networks) == 0 && len(c.state.NetworkStatus) != 1:
|
||||
case len(networks) > 0 && len(networks) != len(c.state.NetworkStatus):
|
||||
return errors.Wrapf(define.ErrInternal, "network mismatch: asked to join %d CNI networks but got %d CNI results", len(networks), len(c.state.NetworkStatus))
|
||||
case len(networks) == 0 && len(c.state.NetworkStatus) != 1:
|
||||
return errors.Wrapf(define.ErrInternal, "network mismatch: did not specify CNI networks but joined more than one (%d)", len(c.state.NetworkStatus))
|
||||
case len(c.config.Networks) == 0 && cniDefaultNetwork == "":
|
||||
case len(networks) == 0 && cniDefaultNetwork == "":
|
||||
return errors.Wrapf(define.ErrInternal, "could not retrieve name of CNI default network")
|
||||
}
|
||||
|
||||
@@ -656,11 +661,11 @@ func (c *Container) removeIPv4Allocations() error {
|
||||
continue
|
||||
}
|
||||
candidate := ""
|
||||
if len(c.config.Networks) > 0 {
|
||||
if len(networks) > 0 {
|
||||
// CNI returns networks in order we passed them.
|
||||
// So our index into results should be our index
|
||||
// into networks.
|
||||
candidate = filepath.Join(cniNetworksDir, c.config.Networks[index], ctrIP.Address.IP.String())
|
||||
candidate = filepath.Join(cniNetworksDir, networks[index], ctrIP.Address.IP.String())
|
||||
} else {
|
||||
candidate = filepath.Join(cniNetworksDir, cniDefaultNetwork, ctrIP.Address.IP.String())
|
||||
}
|
||||
|
||||
@@ -575,6 +575,8 @@ type InspectAdditionalNetwork struct {
|
||||
// Links is presently unused and maintained exclusively for
|
||||
// compatibility.
|
||||
Links []string `json:"Links"`
|
||||
// Aliases are any network aliases the container has in this network.
|
||||
Aliases []string `json:"Aliases,omitempty"`
|
||||
}
|
||||
|
||||
// InspectNetworkSettings holds information about the network settings of the
|
||||
|
||||
@@ -33,9 +33,6 @@ var (
|
||||
// ErrNoAliases indicates that the container does not have any network
|
||||
// aliases.
|
||||
ErrNoAliases = errors.New("no aliases for container")
|
||||
// ErrNoAliasesForNetwork indicates that the container has no aliases
|
||||
// for a specific network.
|
||||
ErrNoAliasesForNetwork = errors.New("no aliases for network")
|
||||
|
||||
// ErrCtrExists indicates a container with the same name or ID already
|
||||
// exists
|
||||
@@ -49,9 +46,9 @@ var (
|
||||
// ErrExecSessionExists indicates an exec session with the same ID
|
||||
// already exists.
|
||||
ErrExecSessionExists = errors.New("exec session already exists")
|
||||
// ErrAliasExists indicates that a network alias with the same name
|
||||
// already exists in the network.
|
||||
ErrAliasExists = errors.New("alias already exists")
|
||||
// ErrNetworkExists indicates that a network with the given name already
|
||||
// exists.
|
||||
ErrNetworkExists = errors.New("network already exists")
|
||||
|
||||
// ErrCtrStateInvalid indicates a container is in an improper state for
|
||||
// the requested operation
|
||||
|
||||
@@ -31,8 +31,7 @@ type InMemoryState struct {
|
||||
ctrExecSessions map[string][]string
|
||||
// Maps pod ID to a map of container ID to container struct.
|
||||
podContainers map[string]map[string]*Container
|
||||
// Maps network name to alias to container ID
|
||||
networkAliases map[string]map[string]string
|
||||
ctrNetworks map[string][]string
|
||||
// Maps container ID to network name to list of aliases.
|
||||
ctrNetworkAliases map[string]map[string][]string
|
||||
// Global name registry - ensures name uniqueness and performs lookups.
|
||||
@@ -69,7 +68,7 @@ func NewInMemoryState() (State, error) {
|
||||
|
||||
state.podContainers = make(map[string]map[string]*Container)
|
||||
|
||||
state.networkAliases = make(map[string]map[string]string)
|
||||
state.ctrNetworks = make(map[string][]string)
|
||||
state.ctrNetworkAliases = make(map[string]map[string][]string)
|
||||
|
||||
state.nameIndex = registrar.NewRegistrar()
|
||||
@@ -293,7 +292,7 @@ func (s *InMemoryState) AddContainer(ctr *Container) error {
|
||||
}
|
||||
|
||||
// Check network aliases
|
||||
for network, aliases := range ctr.config.NetworkAliases {
|
||||
for network := range ctr.config.NetworkAliases {
|
||||
inNet := false
|
||||
for _, net := range ctr.config.Networks {
|
||||
if net == network {
|
||||
@@ -304,19 +303,6 @@ func (s *InMemoryState) AddContainer(ctr *Container) error {
|
||||
if !inNet {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s has network aliases for network %q but is not joined to network", ctr.ID(), network)
|
||||
}
|
||||
|
||||
allNetAliases, ok := s.networkAliases[network]
|
||||
if ok {
|
||||
for _, alias := range aliases {
|
||||
// Check if alias is a name
|
||||
if _, err := s.nameIndex.Get(alias); err == nil {
|
||||
return define.ErrInvalidArg
|
||||
}
|
||||
if _, ok := allNetAliases[alias]; ok {
|
||||
return define.ErrAliasExists
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There are potential race conditions with this
|
||||
@@ -375,46 +361,17 @@ func (s *InMemoryState) AddContainer(ctr *Container) error {
|
||||
s.addCtrToVolDependsMap(ctr.ID(), vol.Name)
|
||||
}
|
||||
|
||||
for _, network := range ctr.config.Networks {
|
||||
allNetAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
continue
|
||||
// Add networks
|
||||
newNets := make([]string, 0, len(ctr.config.Networks))
|
||||
for _, net := range ctr.config.Networks {
|
||||
if net == "" {
|
||||
return define.ErrInvalidArg
|
||||
}
|
||||
otherCtrID, ok := allNetAliases[ctr.Name()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
delete(allNetAliases, ctr.Name())
|
||||
|
||||
otherCtrAliases, ok := s.ctrNetworkAliases[otherCtrID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
otherCtrNetAliases, ok := otherCtrAliases[network]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
newAliases := []string{}
|
||||
for _, alias := range otherCtrNetAliases {
|
||||
if alias != ctr.Name() {
|
||||
newAliases = append(newAliases, alias)
|
||||
}
|
||||
}
|
||||
otherCtrAliases[network] = newAliases
|
||||
newNets = append(newNets, net)
|
||||
}
|
||||
s.ctrNetworks[ctr.ID()] = newNets
|
||||
|
||||
// Add network aliases
|
||||
for network, aliases := range ctr.config.NetworkAliases {
|
||||
allNetAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
allNetAliases = make(map[string]string)
|
||||
s.networkAliases[network] = allNetAliases
|
||||
}
|
||||
|
||||
for _, alias := range aliases {
|
||||
allNetAliases[alias] = ctr.ID()
|
||||
}
|
||||
}
|
||||
s.ctrNetworkAliases[ctr.ID()] = ctr.config.NetworkAliases
|
||||
|
||||
return nil
|
||||
@@ -480,18 +437,12 @@ func (s *InMemoryState) RemoveContainer(ctr *Container) error {
|
||||
}
|
||||
|
||||
// Remove our network aliases
|
||||
ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()]
|
||||
if ok {
|
||||
for network, aliases := range ctrAliases {
|
||||
netAliases, ok := s.networkAliases[network]
|
||||
if ok {
|
||||
for _, alias := range aliases {
|
||||
delete(netAliases, alias)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := s.ctrNetworkAliases[ctr.ID()]; ok {
|
||||
delete(s.ctrNetworkAliases, ctr.ID())
|
||||
}
|
||||
if _, ok := s.ctrNetworks[ctr.ID()]; ok {
|
||||
delete(s.ctrNetworks, ctr.ID())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -569,6 +520,26 @@ func (s *InMemoryState) AllContainers() ([]*Container, error) {
|
||||
return ctrs, nil
|
||||
}
|
||||
|
||||
// Get all networks this container is present in.
|
||||
func (s *InMemoryState) GetNetworks(ctr *Container) ([]string, error) {
|
||||
if !ctr.valid {
|
||||
return nil, define.ErrCtrRemoved
|
||||
}
|
||||
|
||||
ctr, ok := s.containers[ctr.ID()]
|
||||
if !ok {
|
||||
ctr.valid = false
|
||||
return nil, define.ErrNoSuchCtr
|
||||
}
|
||||
|
||||
ctrNetworks, ok := s.ctrNetworks[ctr.ID()]
|
||||
if !ok {
|
||||
return nil, define.ErrNoSuchNetwork
|
||||
}
|
||||
|
||||
return ctrNetworks, nil
|
||||
}
|
||||
|
||||
// GetNetworkAliases returns network aliases for the given container in the
|
||||
// given network.
|
||||
func (s *InMemoryState) GetNetworkAliases(ctr *Container, network string) ([]string, error) {
|
||||
@@ -582,6 +553,7 @@ func (s *InMemoryState) GetNetworkAliases(ctr *Container, network string) ([]str
|
||||
|
||||
ctr, ok := s.containers[ctr.ID()]
|
||||
if !ok {
|
||||
ctr.valid = false
|
||||
return nil, define.ErrNoSuchCtr
|
||||
}
|
||||
|
||||
@@ -615,6 +587,7 @@ func (s *InMemoryState) GetAllNetworkAliases(ctr *Container) (map[string][]strin
|
||||
|
||||
ctr, ok := s.containers[ctr.ID()]
|
||||
if !ok {
|
||||
ctr.valid = false
|
||||
return nil, define.ErrNoSuchCtr
|
||||
}
|
||||
|
||||
@@ -626,9 +599,8 @@ func (s *InMemoryState) GetAllNetworkAliases(ctr *Container) (map[string][]strin
|
||||
return ctrAliases, nil
|
||||
}
|
||||
|
||||
// SetNetworkAliases sets network aliases for the given container in the given
|
||||
// network.
|
||||
func (s *InMemoryState) SetNetworkAliases(ctr *Container, network string, aliases []string) error {
|
||||
// NetworkConnect connects to the given network
|
||||
func (s *InMemoryState) NetworkConnect(ctr *Container, network string, aliases []string) error {
|
||||
if !ctr.valid {
|
||||
return define.ErrCtrRemoved
|
||||
}
|
||||
@@ -639,55 +611,37 @@ func (s *InMemoryState) SetNetworkAliases(ctr *Container, network string, aliase
|
||||
|
||||
ctr, ok := s.containers[ctr.ID()]
|
||||
if !ok {
|
||||
ctr.valid = false
|
||||
return define.ErrNoSuchCtr
|
||||
}
|
||||
|
||||
inNet := false
|
||||
for _, net := range ctr.config.Networks {
|
||||
ctrNetworks, ok := s.ctrNetworks[ctr.ID()]
|
||||
if !ok {
|
||||
return define.ErrNoSuchNetwork
|
||||
}
|
||||
for _, net := range ctrNetworks {
|
||||
if net == network {
|
||||
inNet = true
|
||||
}
|
||||
}
|
||||
if !inNet {
|
||||
return define.ErrInvalidArg
|
||||
if inNet {
|
||||
return define.ErrNoSuchNetwork
|
||||
}
|
||||
s.ctrNetworks[ctr.ID()] = append(ctrNetworks, network)
|
||||
|
||||
ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()]
|
||||
if !ok {
|
||||
ctrAliases = make(map[string][]string)
|
||||
s.ctrNetworkAliases[ctr.ID()] = ctrAliases
|
||||
}
|
||||
netAliases, ok := ctrAliases[network]
|
||||
if !ok {
|
||||
netAliases = []string{}
|
||||
ctrAliases[network] = netAliases
|
||||
}
|
||||
|
||||
allAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
allAliases = make(map[string]string)
|
||||
s.networkAliases[network] = allAliases
|
||||
}
|
||||
|
||||
for _, alias := range netAliases {
|
||||
delete(allAliases, alias)
|
||||
}
|
||||
|
||||
for _, newAlias := range aliases {
|
||||
if _, ok := allAliases[newAlias]; ok {
|
||||
return define.ErrAliasExists
|
||||
}
|
||||
allAliases[newAlias] = ctr.ID()
|
||||
}
|
||||
|
||||
ctrAliases[network] = aliases
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveNetworkAliases removes network aliases from the given container in the
|
||||
// given network.
|
||||
func (s *InMemoryState) RemoveNetworkAliases(ctr *Container, network string) error {
|
||||
// Disconnect from the given network and remove all aliases in it.
|
||||
func (s *InMemoryState) NetworkDisconnect(ctr *Container, network string) error {
|
||||
if !ctr.valid {
|
||||
return define.ErrCtrRemoved
|
||||
}
|
||||
@@ -698,73 +652,36 @@ func (s *InMemoryState) RemoveNetworkAliases(ctr *Container, network string) err
|
||||
|
||||
ctr, ok := s.containers[ctr.ID()]
|
||||
if !ok {
|
||||
ctr.valid = false
|
||||
return define.ErrNoSuchCtr
|
||||
}
|
||||
|
||||
ctrNetworks, ok := s.ctrNetworks[ctr.ID()]
|
||||
if !ok {
|
||||
return define.ErrNoSuchNetwork
|
||||
}
|
||||
inNet := false
|
||||
for _, net := range ctr.config.Networks {
|
||||
remainingNets := make([]string, 0, len(ctrNetworks))
|
||||
for _, net := range ctrNetworks {
|
||||
if net == network {
|
||||
inNet = true
|
||||
break
|
||||
} else {
|
||||
remainingNets = append(remainingNets, net)
|
||||
}
|
||||
}
|
||||
if !inNet {
|
||||
return define.ErrInvalidArg
|
||||
return define.ErrNoSuchNetwork
|
||||
}
|
||||
s.ctrNetworks[ctr.ID()] = remainingNets
|
||||
|
||||
ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()]
|
||||
if !ok {
|
||||
ctrAliases = make(map[string][]string)
|
||||
s.ctrNetworkAliases[ctr.ID()] = ctrAliases
|
||||
}
|
||||
netAliases, ok := ctrAliases[network]
|
||||
if !ok {
|
||||
netAliases = []string{}
|
||||
ctrAliases[network] = netAliases
|
||||
}
|
||||
|
||||
allAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
allAliases = make(map[string]string)
|
||||
s.networkAliases[network] = allAliases
|
||||
}
|
||||
|
||||
for _, alias := range netAliases {
|
||||
delete(allAliases, alias)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllAliasesForNetwork gets all the aliases for a single network.
|
||||
func (s *InMemoryState) GetAllAliasesForNetwork(network string) (map[string]string, error) {
|
||||
if network == "" {
|
||||
return nil, errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
|
||||
}
|
||||
|
||||
allAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
// Can't tell if the network exists.
|
||||
// Assume it does.
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
|
||||
return allAliases, nil
|
||||
}
|
||||
|
||||
// RemoveAllAliasesForNetwork removes all the aliases for a given network.
|
||||
func (s *InMemoryState) RemoveAllAliasesForNetwork(network string) error {
|
||||
if network == "" {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
|
||||
}
|
||||
|
||||
if _, ok := s.networkAliases[network]; ok {
|
||||
delete(s.networkAliases, network)
|
||||
}
|
||||
|
||||
for _, ctrAliases := range s.ctrNetworkAliases {
|
||||
if _, ok := ctrAliases[network]; ok {
|
||||
delete(ctrAliases, network)
|
||||
}
|
||||
if _, ok := ctrAliases[network]; ok {
|
||||
delete(ctrAliases, network)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1422,7 +1339,7 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
|
||||
}
|
||||
|
||||
// Check network aliases
|
||||
for network, aliases := range ctr.config.NetworkAliases {
|
||||
for network := range ctr.config.NetworkAliases {
|
||||
inNet := false
|
||||
for _, net := range ctr.config.Networks {
|
||||
if net == network {
|
||||
@@ -1433,19 +1350,6 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
|
||||
if !inNet {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s has network aliases for network %q but is not joined to network", ctr.ID(), network)
|
||||
}
|
||||
|
||||
allNetAliases, ok := s.networkAliases[network]
|
||||
if ok {
|
||||
for _, alias := range aliases {
|
||||
// Check if alias is a name
|
||||
if _, err := s.nameIndex.Get(alias); err == nil {
|
||||
return define.ErrInvalidArg
|
||||
}
|
||||
if _, ok := allNetAliases[alias]; ok {
|
||||
return define.ErrAliasExists
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve pod containers list
|
||||
@@ -1525,46 +1429,17 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
|
||||
s.addCtrToVolDependsMap(ctr.ID(), vol.Name)
|
||||
}
|
||||
|
||||
for _, network := range ctr.config.Networks {
|
||||
allNetAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
continue
|
||||
// Add networks
|
||||
newNets := make([]string, 0, len(ctr.config.Networks))
|
||||
for _, net := range ctr.config.Networks {
|
||||
if net == "" {
|
||||
return define.ErrInvalidArg
|
||||
}
|
||||
otherCtrID, ok := allNetAliases[ctr.Name()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
delete(allNetAliases, ctr.Name())
|
||||
|
||||
otherCtrAliases, ok := s.ctrNetworkAliases[otherCtrID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
otherCtrNetAliases, ok := otherCtrAliases[network]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
newAliases := []string{}
|
||||
for _, alias := range otherCtrNetAliases {
|
||||
if alias != ctr.Name() {
|
||||
newAliases = append(newAliases, alias)
|
||||
}
|
||||
}
|
||||
otherCtrAliases[network] = newAliases
|
||||
newNets = append(newNets, net)
|
||||
}
|
||||
s.ctrNetworks[ctr.ID()] = newNets
|
||||
|
||||
// Add network aliases
|
||||
for network, aliases := range ctr.config.NetworkAliases {
|
||||
allNetAliases, ok := s.networkAliases[network]
|
||||
if !ok {
|
||||
allNetAliases = make(map[string]string)
|
||||
s.networkAliases[network] = allNetAliases
|
||||
}
|
||||
|
||||
for _, alias := range aliases {
|
||||
allNetAliases[alias] = ctr.ID()
|
||||
}
|
||||
}
|
||||
s.ctrNetworkAliases[ctr.ID()] = ctr.config.NetworkAliases
|
||||
|
||||
return nil
|
||||
@@ -1648,18 +1523,12 @@ func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
|
||||
}
|
||||
|
||||
// Remove our network aliases
|
||||
ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()]
|
||||
if ok {
|
||||
for network, aliases := range ctrAliases {
|
||||
netAliases, ok := s.networkAliases[network]
|
||||
if ok {
|
||||
for _, alias := range aliases {
|
||||
delete(netAliases, alias)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := s.ctrNetworkAliases[ctr.ID()]; ok {
|
||||
delete(s.ctrNetworkAliases, ctr.ID())
|
||||
}
|
||||
if _, ok := s.ctrNetworks[ctr.ID()]; ok {
|
||||
delete(s.ctrNetworks, ctr.ID())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -104,7 +104,11 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
|
||||
|
||||
podName := getCNIPodName(ctr)
|
||||
|
||||
podNetwork := r.getPodNetwork(ctr.ID(), podName, ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP, requestedMAC)
|
||||
networks, err := ctr.networks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
podNetwork := r.getPodNetwork(ctr.ID(), podName, ctrNS.Path(), networks, ctr.config.PortMappings, requestedIP, requestedMAC)
|
||||
aliases, err := ctr.runtime.state.GetAllNetworkAliases(ctr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -209,7 +213,11 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
|
||||
if ctr.config.NetMode.IsSlirp4netns() {
|
||||
return r.setupSlirp4netns(ctr)
|
||||
}
|
||||
if len(ctr.config.Networks) > 0 {
|
||||
networks, err := ctr.networks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(networks) > 0 {
|
||||
// set up port forwarder for CNI-in-slirp4netns
|
||||
netnsPath := ctr.state.NetNS.Path()
|
||||
// TODO: support slirp4netns port forwarder as well
|
||||
@@ -725,6 +733,11 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
|
||||
|
||||
logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID())
|
||||
|
||||
networks, err := ctr.networks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// rootless containers do not use the CNI plugin directly
|
||||
if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() {
|
||||
var requestedIP net.IP
|
||||
@@ -745,7 +758,7 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
|
||||
requestedMAC = ctr.config.StaticMAC
|
||||
}
|
||||
|
||||
podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP, requestedMAC)
|
||||
podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), networks, ctr.config.PortMappings, requestedIP, requestedMAC)
|
||||
|
||||
if err := r.netPlugin.TearDownPod(podNetwork); err != nil {
|
||||
return errors.Wrapf(err, "error tearing down CNI namespace configuration for container %s", ctr.ID())
|
||||
@@ -753,7 +766,7 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
|
||||
}
|
||||
|
||||
// CNI-in-slirp4netns
|
||||
if rootless.IsRootless() && len(ctr.config.Networks) != 0 {
|
||||
if rootless.IsRootless() && len(networks) != 0 {
|
||||
if err := DeallocRootlessCNI(context.Background(), ctr); err != nil {
|
||||
return errors.Wrapf(err, "error tearing down CNI-in-slirp4netns for container %s", ctr.ID())
|
||||
}
|
||||
@@ -839,13 +852,18 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
|
||||
settings := new(define.InspectNetworkSettings)
|
||||
settings.Ports = makeInspectPortBindings(c.config.PortMappings)
|
||||
|
||||
networks, err := c.networks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We can't do more if the network is down.
|
||||
if c.state.NetNS == nil {
|
||||
// We still want to make dummy configurations for each CNI net
|
||||
// the container joined.
|
||||
if len(c.config.Networks) > 0 {
|
||||
settings.Networks = make(map[string]*define.InspectAdditionalNetwork, len(c.config.Networks))
|
||||
for _, net := range c.config.Networks {
|
||||
if len(networks) > 0 {
|
||||
settings.Networks = make(map[string]*define.InspectAdditionalNetwork, len(networks))
|
||||
for _, net := range networks {
|
||||
cniNet := new(define.InspectAdditionalNetwork)
|
||||
cniNet.NetworkID = net
|
||||
settings.Networks[net] = cniNet
|
||||
@@ -864,16 +882,16 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
|
||||
}
|
||||
|
||||
// If we have CNI networks - handle that here
|
||||
if len(c.config.Networks) > 0 {
|
||||
if len(c.config.Networks) != len(c.state.NetworkStatus) {
|
||||
return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(c.config.Networks), len(c.state.NetworkStatus))
|
||||
if len(networks) > 0 {
|
||||
if len(networks) != len(c.state.NetworkStatus) {
|
||||
return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(networks), len(c.state.NetworkStatus))
|
||||
}
|
||||
|
||||
settings.Networks = make(map[string]*define.InspectAdditionalNetwork)
|
||||
|
||||
// CNI results should be in the same order as the list of
|
||||
// networks we pass into CNI.
|
||||
for index, name := range c.config.Networks {
|
||||
for index, name := range networks {
|
||||
cniResult := c.state.NetworkStatus[index]
|
||||
addedNet := new(define.InspectAdditionalNetwork)
|
||||
addedNet.NetworkID = name
|
||||
@@ -882,6 +900,13 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aliases, err := c.runtime.state.GetNetworkAliases(c, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedNet.Aliases = aliases
|
||||
|
||||
addedNet.InspectBasicNetworkConfig = basicConfig
|
||||
|
||||
settings.Networks[name] = addedNet
|
||||
|
||||
@@ -40,8 +40,12 @@ const (
|
||||
//
|
||||
// AllocRootlessCNI does not lock c. c should be already locked.
|
||||
func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.Result, error) {
|
||||
if len(c.config.Networks) == 0 {
|
||||
return nil, nil, errors.New("allocRootlessCNI shall not be called when len(c.config.Networks) == 0")
|
||||
networks, err := c.networks()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(networks) == 0 {
|
||||
return nil, nil, errors.New("rootless CNI networking requires that the container has joined at least one CNI network")
|
||||
}
|
||||
l, err := getRootlessCNIInfraLock(c.runtime)
|
||||
if err != nil {
|
||||
@@ -54,8 +58,8 @@ func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.
|
||||
return nil, nil, err
|
||||
}
|
||||
k8sPodName := getCNIPodName(c) // passed to CNI as K8S_POD_NAME
|
||||
cniResults := make([]*cnitypes.Result, len(c.config.Networks))
|
||||
for i, nw := range c.config.Networks {
|
||||
cniResults := make([]*cnitypes.Result, len(networks))
|
||||
for i, nw := range networks {
|
||||
cniRes, err := rootlessCNIInfraCallAlloc(infra, c.ID(), nw, k8sPodName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -77,8 +81,12 @@ func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.
|
||||
//
|
||||
// DeallocRootlessCNI does not lock c. c should be already locked.
|
||||
func DeallocRootlessCNI(ctx context.Context, c *Container) error {
|
||||
if len(c.config.Networks) == 0 {
|
||||
return errors.New("deallocRootlessCNI shall not be called when len(c.config.Networks) == 0")
|
||||
networks, err := c.networks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(networks) == 0 {
|
||||
return errors.New("rootless CNI networking requires that the container has joined at least one CNI network")
|
||||
}
|
||||
l, err := getRootlessCNIInfraLock(c.runtime)
|
||||
if err != nil {
|
||||
@@ -91,7 +99,7 @@ func DeallocRootlessCNI(ctx context.Context, c *Container) error {
|
||||
return nil
|
||||
}
|
||||
var errs *multierror.Error
|
||||
for _, nw := range c.config.Networks {
|
||||
for _, nw := range networks {
|
||||
err := rootlessCNIInfraCallDelloc(infra, c.ID(), nw)
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
|
||||
@@ -98,20 +98,18 @@ type State interface {
|
||||
// returned.
|
||||
AllContainers() ([]*Container, error)
|
||||
|
||||
// Get networks the container is currently connected to.
|
||||
GetNetworks(ctr *Container) ([]string, error)
|
||||
// Get network aliases for the given container in the given network.
|
||||
GetNetworkAliases(ctr *Container, network string) ([]string, error)
|
||||
// Get all network aliases for the given container.
|
||||
GetAllNetworkAliases(ctr *Container) (map[string][]string, error)
|
||||
// Set network aliases for the given container in the given network.
|
||||
SetNetworkAliases(ctr *Container, network string, aliases []string) error
|
||||
// Remove network aliases for the given container in the given network.
|
||||
RemoveNetworkAliases(ctr *Container, network string) error
|
||||
// GetAllAliasesForNetwork returns all the aliases for a given
|
||||
// network. Returns a map of alias to container ID.
|
||||
GetAllAliasesForNetwork(network string) (map[string]string, error)
|
||||
// RemoveAllAliasesForNetwork removes all the aliases for a given
|
||||
// network.
|
||||
RemoveAllAliasesForNetwork(network string) error
|
||||
// Add the container to the given network, adding the given aliases
|
||||
// (if present).
|
||||
NetworkConnect(ctr *Container, network string, aliases []string) error
|
||||
// Remove the container from the given network, removing all aliases for
|
||||
// the container in that network in the process.
|
||||
NetworkDisconnect(ctr *Container, network string) error
|
||||
|
||||
// Return a container config from the database by full ID
|
||||
GetContainerConfig(id string) (*ContainerConfig, error)
|
||||
|
||||
@@ -1345,224 +1345,6 @@ func TestAddContainerNetworkAliasesButNoMatchingNetwork(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddContainerNetworkAliasConflictWithName(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr1, err := getTestCtr1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName := "testnet"
|
||||
testCtr1.config.Networks = []string{netName}
|
||||
testCtr1.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr1.config.NetworkAliases[netName] = []string{"alias1"}
|
||||
|
||||
testCtr2, err := getTestCtr2(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testCtr2.config.Networks = []string{netName}
|
||||
testCtr2.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr2.config.NetworkAliases[netName] = []string{testCtr1.Name()}
|
||||
|
||||
err = state.AddContainer(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = state.AddContainer(testCtr2)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddContainerNetworkAliasConflictWithAlias(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr1, err := getTestCtr1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName := "testnet"
|
||||
aliasName := "alias1"
|
||||
testCtr1.config.Networks = []string{netName}
|
||||
testCtr1.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr1.config.NetworkAliases[netName] = []string{aliasName}
|
||||
|
||||
testCtr2, err := getTestCtr2(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testCtr2.config.Networks = []string{netName}
|
||||
testCtr2.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr2.config.NetworkAliases[netName] = []string{aliasName}
|
||||
|
||||
err = state.AddContainer(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = state.AddContainer(testCtr2)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddContainerNetworkAliasConflictWithAliasButDifferentNets(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr1, err := getTestCtr1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName := "testnet"
|
||||
aliasName := "alias1"
|
||||
testCtr1.config.Networks = []string{netName}
|
||||
testCtr1.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr1.config.NetworkAliases[netName] = []string{aliasName}
|
||||
|
||||
testCtr2, err := getTestCtr2(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName2 := "testnet2"
|
||||
testCtr2.config.Networks = []string{netName2}
|
||||
testCtr2.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr2.config.NetworkAliases[netName2] = []string{aliasName}
|
||||
|
||||
err = state.AddContainer(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = state.AddContainer(testCtr2)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddContainerNameConflictsWithAliasRemovesAlias(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr1, err := getTestCtr1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testCtr2, err := getTestCtr2(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName := "testnet"
|
||||
aliasName := testCtr2.Name()
|
||||
testCtr1.config.Networks = []string{netName}
|
||||
testCtr1.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr1.config.NetworkAliases[netName] = []string{aliasName}
|
||||
|
||||
testCtr2.config.Networks = []string{netName}
|
||||
|
||||
err = state.AddContainer(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = state.AddContainer(testCtr2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
aliases, err := state.GetNetworkAliases(testCtr1, netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(aliases))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNetworkAliasAddAndRemoveSingleContainer(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr, err := getTestCtr1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName := "testnet"
|
||||
testCtr.config.Networks = []string{netName}
|
||||
testCtr.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr.config.NetworkAliases[netName] = []string{"alias1"}
|
||||
|
||||
startAliases, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(startAliases))
|
||||
|
||||
err = state.AddContainer(testCtr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
oneAlias, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(oneAlias))
|
||||
assert.Equal(t, testCtr.ID(), oneAlias["alias1"])
|
||||
|
||||
allAliases, err := state.GetAllNetworkAliases(testCtr)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(allAliases))
|
||||
netAliases, ok := allAliases[netName]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(netAliases))
|
||||
assert.Equal(t, "alias1", netAliases[0])
|
||||
|
||||
ctrNetAliases, err := state.GetNetworkAliases(testCtr, netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(ctrNetAliases))
|
||||
assert.Equal(t, "alias1", ctrNetAliases[0])
|
||||
|
||||
err = state.RemoveContainer(testCtr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
noAliases, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(noAliases))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNetworkAliasAddAndRemoveTwoContainers(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr1, err := getTestCtr1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
netName := "testnet"
|
||||
testCtr1.config.Networks = []string{netName}
|
||||
testCtr1.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr1.config.NetworkAliases[netName] = []string{"alias1"}
|
||||
|
||||
testCtr2, err := getTestCtr2(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testCtr2.config.Networks = []string{netName}
|
||||
testCtr2.config.NetworkAliases = make(map[string][]string)
|
||||
testCtr2.config.NetworkAliases[netName] = []string{"alias2"}
|
||||
|
||||
startAliases, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(startAliases))
|
||||
|
||||
err = state.AddContainer(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
oneAlias, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(oneAlias))
|
||||
assert.Equal(t, testCtr1.ID(), oneAlias["alias1"])
|
||||
|
||||
err = state.AddContainer(testCtr2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
twoAliases, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 2, len(twoAliases))
|
||||
assert.Equal(t, testCtr1.ID(), twoAliases["alias1"])
|
||||
assert.Equal(t, testCtr2.ID(), twoAliases["alias2"])
|
||||
|
||||
allAliases, err := state.GetAllNetworkAliases(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(allAliases))
|
||||
netAliases, ok := allAliases[netName]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(netAliases))
|
||||
assert.Equal(t, "alias1", netAliases[0])
|
||||
|
||||
ctrNetAliases, err := state.GetNetworkAliases(testCtr1, netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(ctrNetAliases))
|
||||
assert.Equal(t, "alias1", ctrNetAliases[0])
|
||||
|
||||
err = state.RemoveContainer(testCtr2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
oneAlias, err = state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(oneAlias))
|
||||
assert.Equal(t, testCtr1.ID(), oneAlias["alias1"])
|
||||
|
||||
err = state.RemoveContainer(testCtr1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
noAliases, err := state.GetAllAliasesForNetwork(netName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(noAliases))
|
||||
})
|
||||
}
|
||||
|
||||
func TestCannotUseBadIDAsDependency(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testCtr, err := getTestCtr1(manager)
|
||||
|
||||
Reference in New Issue
Block a user