diff --git a/source/custom/custom.go b/source/custom/custom.go index fdaf76269..33abb7c7f 100644 --- a/source/custom/custom.go +++ b/source/custom/custom.go @@ -58,7 +58,7 @@ type customSource struct { // Singleton source instance var ( - src customSource + src = customSource{config: newDefaultConfig()} _ source.LabelSource = &src _ source.ConfigurableSource = &src ) diff --git a/source/custom/rules/loaded_kmod_rule.go b/source/custom/rules/loaded_kmod_rule.go index f2a9c84d2..1fdb546f8 100644 --- a/source/custom/rules/loaded_kmod_rule.go +++ b/source/custom/rules/loaded_kmod_rule.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors. +Copyright 2020-2021 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,44 +18,26 @@ package rules import ( "fmt" - "io/ioutil" - "strings" + + "sigs.k8s.io/node-feature-discovery/source" + "sigs.k8s.io/node-feature-discovery/source/kernel" ) // LoadedKModRule matches loaded kernel modules in the system type LoadedKModRule []string -const kmodProcfsPath = "/proc/modules" - // Match loaded kernel modules on provided list of kernel modules func (kmods *LoadedKModRule) Match() (bool, error) { - loadedModules, err := kmods.getLoadedModules() - if err != nil { - return false, fmt.Errorf("failed to get loaded kernel modules. %s", err.Error()) + modules, ok := source.GetFeatureSource("kernel").GetFeatures().Keys[kernel.LoadedModuleFeature] + if !ok { + return false, fmt.Errorf("info about loaded modules not available") } + for _, kmod := range *kmods { - if _, ok := loadedModules[kmod]; !ok { + if _, ok := modules.Elements[kmod]; !ok { // kernel module not loaded return false, nil } } return true, nil } - -func (kmods *LoadedKModRule) getLoadedModules() (map[string]struct{}, error) { - out, err := ioutil.ReadFile(kmodProcfsPath) - if err != nil { - return nil, fmt.Errorf("failed to read file %s: %s", kmodProcfsPath, err.Error()) - } - - loadedMods := make(map[string]struct{}) - for _, line := range strings.Split(string(out), "\n") { - // skip empty lines - if len(line) == 0 { - continue - } - // append loaded module - loadedMods[strings.Fields(line)[0]] = struct{}{} - } - return loadedMods, nil -} diff --git a/source/kernel/kernel.go b/source/kernel/kernel.go index 24a8824a1..a24fba650 100644 --- a/source/kernel/kernel.go +++ b/source/kernel/kernel.go @@ -29,9 +29,10 @@ import ( const Name = "kernel" const ( - ConfigFeature = "config" - SelinuxFeature = "selinux" - VersionFeature = "version" + ConfigFeature = "config" + LoadedModuleFeature = "loadedmodule" + SelinuxFeature = "selinux" + VersionFeature = "version" ) // Configuration file options @@ -129,6 +130,12 @@ func (s *kernelSource) Discover() error { s.features.Values[ConfigFeature] = feature.NewValueFeatures(kconfig) } + if kmods, err := getLoadedModules(); err != nil { + klog.Errorf("failed to get loaded kernel modules: %v", err) + } else { + s.features.Keys[LoadedModuleFeature] = feature.NewKeyFeatures(kmods...) + } + if selinux, err := SelinuxEnabled(); err != nil { klog.Warning(err) } else { diff --git a/source/kernel/modules.go b/source/kernel/modules.go new file mode 100644 index 000000000..54dfdf4e1 --- /dev/null +++ b/source/kernel/modules.go @@ -0,0 +1,44 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kernel + +import ( + "fmt" + "io/ioutil" + "strings" +) + +const kmodProcfsPath = "/proc/modules" + +func getLoadedModules() ([]string, error) { + out, err := ioutil.ReadFile(kmodProcfsPath) + if err != nil { + return nil, fmt.Errorf("failed to read file %s: %s", kmodProcfsPath, err.Error()) + } + + lines := strings.Split(string(out), "\n") + loadedMods := make([]string, len(lines)) + for _, line := range lines { + // skip empty lines + if len(line) == 0 { + continue + } + // append loaded module + loadedMods = append(loadedMods, strings.Fields(line)[0]) + } + return loadedMods, nil +}