89 lines
2.4 KiB
Go
89 lines
2.4 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package fingerprint
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/containernetworking/cni/libcni"
|
|
"github.com/hashicorp/go-hclog"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
)
|
|
|
|
// CNIFingerprint creates a fingerprint of the CNI configuration(s) on the
|
|
// Nomad client.
|
|
type CNIFingerprint struct {
|
|
StaticFingerprinter
|
|
logger hclog.Logger
|
|
}
|
|
|
|
func NewCNIFingerprint(logger hclog.Logger) Fingerprint {
|
|
return &CNIFingerprint{logger: logger}
|
|
}
|
|
|
|
func (f *CNIFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintResponse) error {
|
|
confDir := req.Config.CNIConfigDir
|
|
networks := map[string]struct{}{}
|
|
if _, err := os.Stat(confDir); os.IsNotExist(err) {
|
|
f.logger.Debug("CNI config dir is not set or does not exist, skipping", "cni_config_dir", confDir)
|
|
resp.Detected = false
|
|
return nil
|
|
}
|
|
|
|
files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to detect CNI conf files: %v", err)
|
|
}
|
|
|
|
for _, confFile := range files {
|
|
if strings.HasSuffix(confFile, ".conflist") {
|
|
confList, err := libcni.ConfListFromFile(confFile)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load CNI config list file %s: %v", confFile, err)
|
|
}
|
|
if _, ok := networks[confList.Name]; ok {
|
|
f.logger.Warn("duplicate CNI config names found, ignoring file", "name", confList.Name, "file", confFile)
|
|
continue
|
|
}
|
|
networks[confList.Name] = struct{}{}
|
|
} else {
|
|
conf, err := libcni.ConfFromFile(confFile)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load CNI config file %s: %v", confFile, err)
|
|
}
|
|
if _, ok := networks[conf.Network.Name]; ok {
|
|
f.logger.Warn("duplicate CNI config names found, ignoring file", "name", conf.Network.Name, "file", confFile)
|
|
continue
|
|
}
|
|
networks[conf.Network.Name] = struct{}{}
|
|
}
|
|
}
|
|
|
|
var nodeNetworks structs.Networks
|
|
var newNodeNetworks []*structs.NodeNetworkResource
|
|
|
|
for name := range networks {
|
|
mode := fmt.Sprintf("cni/%s", name)
|
|
nodeNetworks = append(nodeNetworks, &structs.NetworkResource{
|
|
Mode: mode,
|
|
})
|
|
newNodeNetworks = append(newNodeNetworks, &structs.NodeNetworkResource{
|
|
Mode: mode,
|
|
})
|
|
f.logger.Debug("detected CNI network", "name", name)
|
|
}
|
|
|
|
resp.NodeResources = &structs.NodeResources{
|
|
Networks: nodeNetworks,
|
|
NodeNetworks: newNodeNetworks,
|
|
}
|
|
|
|
resp.Detected = true
|
|
return nil
|
|
}
|
|
|
|
func (f *CNIFingerprint) Reload() {}
|