github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/network/files.go (about)

     1  package network
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"sort"
     8  	"strings"
     9  
    10  	"github.com/containernetworking/cni/libcni"
    11  	"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // LoadCNIConfsFromDir loads all the CNI configurations from a dir
    16  func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
    17  	var configs []*libcni.NetworkConfigList
    18  	files, err := libcni.ConfFiles(dir, []string{".conflist"})
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  	sort.Strings(files)
    23  
    24  	for _, confFile := range files {
    25  		conf, err := libcni.ConfListFromFile(confFile)
    26  		if err != nil {
    27  			return nil, errors.Wrapf(err, "in %s", confFile)
    28  		}
    29  		configs = append(configs, conf)
    30  	}
    31  	return configs, nil
    32  }
    33  
    34  // GetCNIConfigPathByName finds a CNI network by name and
    35  // returns its configuration file path
    36  func GetCNIConfigPathByName(name string) (string, error) {
    37  	files, err := libcni.ConfFiles(CNIConfigDir, []string{".conflist"})
    38  	if err != nil {
    39  		return "", err
    40  	}
    41  	for _, confFile := range files {
    42  		conf, err := libcni.ConfListFromFile(confFile)
    43  		if err != nil {
    44  			return "", errors.Wrapf(err, "in %s", confFile)
    45  		}
    46  		if conf.Name == name {
    47  			return confFile, nil
    48  		}
    49  	}
    50  	return "", errors.Wrap(ErrNetworkNotFound, fmt.Sprintf("unable to find network configuration for %s", name))
    51  }
    52  
    53  // ReadRawCNIConfByName reads the raw CNI configuration for a CNI
    54  // network by name
    55  func ReadRawCNIConfByName(name string) ([]byte, error) {
    56  	confFile, err := GetCNIConfigPathByName(name)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	b, err := ioutil.ReadFile(confFile)
    61  	return b, err
    62  }
    63  
    64  // GetCNIPlugins returns a list of plugins that a given network
    65  // has in the form of a string
    66  func GetCNIPlugins(list *libcni.NetworkConfigList) string {
    67  	var plugins []string
    68  	for _, plug := range list.Plugins {
    69  		plugins = append(plugins, plug.Network.Type)
    70  	}
    71  	return strings.Join(plugins, ",")
    72  }
    73  
    74  // GetNetworksFromFilesystem gets all the networks from the cni configuration
    75  // files
    76  func GetNetworksFromFilesystem() ([]*allocator.Net, error) {
    77  	var cniNetworks []*allocator.Net
    78  	networks, err := LoadCNIConfsFromDir(CNIConfigDir)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	for _, n := range networks {
    83  		for _, cniplugin := range n.Plugins {
    84  			if cniplugin.Network.Type == "bridge" {
    85  				ipamConf := allocator.Net{}
    86  				if err := json.Unmarshal(cniplugin.Bytes, &ipamConf); err != nil {
    87  					return nil, err
    88  				}
    89  				cniNetworks = append(cniNetworks, &ipamConf)
    90  				break
    91  			}
    92  		}
    93  	}
    94  	return cniNetworks, nil
    95  }
    96  
    97  // GetNetworkNamesFromFileSystem gets all the names from the cni network
    98  // configuration files
    99  func GetNetworkNamesFromFileSystem() ([]string, error) {
   100  	var networkNames []string
   101  	networks, err := LoadCNIConfsFromDir(CNIConfigDir)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	for _, n := range networks {
   106  		networkNames = append(networkNames, n.Name)
   107  	}
   108  	return networkNames, nil
   109  }
   110  
   111  // GetInterfaceNameFromConfig returns the interface name for the bridge plugin
   112  func GetInterfaceNameFromConfig(path string) (string, error) {
   113  	var name string
   114  	conf, err := libcni.ConfListFromFile(path)
   115  	if err != nil {
   116  		return "", err
   117  	}
   118  	for _, cniplugin := range conf.Plugins {
   119  		if cniplugin.Network.Type == "bridge" {
   120  			plugin := make(map[string]interface{})
   121  			if err := json.Unmarshal(cniplugin.Bytes, &plugin); err != nil {
   122  				return "", err
   123  			}
   124  			name = plugin["bridge"].(string)
   125  			break
   126  		}
   127  	}
   128  	if len(name) == 0 {
   129  		return "", errors.New("unable to find interface name for network")
   130  	}
   131  	return name, nil
   132  }
   133  
   134  // GetBridgeNamesFromFileSystem is a convenience function to get all the bridge
   135  // names from the configured networks
   136  func GetBridgeNamesFromFileSystem() ([]string, error) {
   137  	var bridgeNames []string
   138  	networks, err := LoadCNIConfsFromDir(CNIConfigDir)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	for _, n := range networks {
   143  		var name string
   144  		// iterate network conflists
   145  		for _, cniplugin := range n.Plugins {
   146  			// iterate plugins
   147  			if cniplugin.Network.Type == "bridge" {
   148  				plugin := make(map[string]interface{})
   149  				if err := json.Unmarshal(cniplugin.Bytes, &plugin); err != nil {
   150  					continue
   151  				}
   152  				name = plugin["bridge"].(string)
   153  			}
   154  		}
   155  		bridgeNames = append(bridgeNames, name)
   156  	}
   157  	return bridgeNames, nil
   158  }