github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/fingerprint/cni.go (about)

     1  package fingerprint
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/containernetworking/cni/libcni"
     9  	"github.com/hashicorp/go-hclog"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  )
    12  
    13  // CNIFingerprint creates a fingerprint of the CNI configuration(s) on the
    14  // Nomad client.
    15  type CNIFingerprint struct {
    16  	StaticFingerprinter
    17  	logger hclog.Logger
    18  }
    19  
    20  func NewCNIFingerprint(logger hclog.Logger) Fingerprint {
    21  	return &CNIFingerprint{logger: logger}
    22  }
    23  
    24  func (f *CNIFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintResponse) error {
    25  	confDir := req.Config.CNIConfigDir
    26  	networks := map[string]struct{}{}
    27  	if _, err := os.Stat(confDir); os.IsNotExist(err) {
    28  		f.logger.Debug("CNI config dir is not set or does not exist, skipping", "cni_config_dir", confDir)
    29  		resp.Detected = false
    30  		return nil
    31  	}
    32  
    33  	files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"})
    34  	if err != nil {
    35  		return fmt.Errorf("failed to detect CNI conf files: %v", err)
    36  	}
    37  
    38  	for _, confFile := range files {
    39  		if strings.HasSuffix(confFile, ".conflist") {
    40  			confList, err := libcni.ConfListFromFile(confFile)
    41  			if err != nil {
    42  				return fmt.Errorf("failed to load CNI config list file %s: %v", confFile, err)
    43  			}
    44  			if _, ok := networks[confList.Name]; ok {
    45  				f.logger.Warn("duplicate CNI config names found, ignoring file", "name", confList.Name, "file", confFile)
    46  				continue
    47  			}
    48  			networks[confList.Name] = struct{}{}
    49  		} else {
    50  			conf, err := libcni.ConfFromFile(confFile)
    51  			if err != nil {
    52  				return fmt.Errorf("failed to load CNI config file %s: %v", confFile, err)
    53  			}
    54  			if _, ok := networks[conf.Network.Name]; ok {
    55  				f.logger.Warn("duplicate CNI config names found, ignoring file", "name", conf.Network.Name, "file", confFile)
    56  				continue
    57  			}
    58  			networks[conf.Network.Name] = struct{}{}
    59  		}
    60  	}
    61  
    62  	var nodeNetworks structs.Networks
    63  	var newNodeNetworks []*structs.NodeNetworkResource
    64  
    65  	for name := range networks {
    66  		mode := fmt.Sprintf("cni/%s", name)
    67  		nodeNetworks = append(nodeNetworks, &structs.NetworkResource{
    68  			Mode: mode,
    69  		})
    70  		newNodeNetworks = append(newNodeNetworks, &structs.NodeNetworkResource{
    71  			Mode: mode,
    72  		})
    73  		f.logger.Debug("detected CNI network", "name", name)
    74  	}
    75  
    76  	resp.NodeResources = &structs.NodeResources{
    77  		Networks:     nodeNetworks,
    78  		NodeNetworks: newNodeNetworks,
    79  	}
    80  
    81  	resp.Detected = true
    82  	return nil
    83  }
    84  
    85  func (f *CNIFingerprint) Reload() {}