mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-28 02:37:11 +00:00
commit
f65def9460
21 changed files with 121 additions and 111 deletions
|
@ -11,8 +11,12 @@ env:
|
|||
services:
|
||||
- docker
|
||||
|
||||
before_script:
|
||||
- curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.27.0
|
||||
|
||||
script:
|
||||
- make gofmt-verify
|
||||
- make ci-lint
|
||||
- make image -e
|
||||
- if [ "$TRAVIS_BRANCH" == master -a -n "$IMAGE_REPO_USER" ]; then
|
||||
set -e;
|
||||
|
|
2
Makefile
2
Makefile
|
@ -55,6 +55,8 @@ gofmt-verify:
|
|||
exit 1; \
|
||||
fi
|
||||
|
||||
ci-lint:
|
||||
golangci-lint run --timeout 5m0s
|
||||
|
||||
test:
|
||||
$(GO_CMD) test ./cmd/... ./pkg/...
|
||||
|
|
|
@ -96,8 +96,8 @@ func argsParse(argv []string) (master.Args, error) {
|
|||
ProgramName,
|
||||
)
|
||||
|
||||
arguments, _ := docopt.Parse(usage, argv, true,
|
||||
fmt.Sprintf("%s %s", ProgramName, version.Get()), false)
|
||||
arguments, _ := docopt.ParseArgs(usage, argv,
|
||||
fmt.Sprintf("%s %s", ProgramName, version.Get()))
|
||||
|
||||
// Parse argument values as usable types.
|
||||
var err error
|
||||
|
|
|
@ -106,8 +106,8 @@ func argsParse(argv []string) (worker.Args, error) {
|
|||
ProgramName,
|
||||
)
|
||||
|
||||
arguments, _ := docopt.Parse(usage, argv, true,
|
||||
fmt.Sprintf("%s %s", ProgramName, version.Get()), false)
|
||||
arguments, _ := docopt.ParseArgs(usage, argv,
|
||||
fmt.Sprintf("%s %s", ProgramName, version.Get()))
|
||||
|
||||
// Parse argument values as usable types.
|
||||
var err error
|
||||
|
|
|
@ -16,14 +16,14 @@ limitations under the License.
|
|||
|
||||
package cpuid
|
||||
|
||||
type CpuidRet struct {
|
||||
type ReturnValue struct {
|
||||
EAX, EBX, ECX, EDX uint32
|
||||
}
|
||||
|
||||
func Cpuid(eax, ecx uint32) *CpuidRet {
|
||||
r := &CpuidRet{}
|
||||
func Cpuid(eax, ecx uint32) *ReturnValue {
|
||||
r := &ReturnValue{}
|
||||
r.EAX, r.EBX, r.ECX, r.EDX = cpuidAsm(eax, ecx)
|
||||
return r
|
||||
}
|
||||
|
||||
func cpuidAsm(eax_arg, ecx_arg uint32) (eax, ebx, ecx, edx uint32)
|
||||
func cpuidAsm(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
|
||||
|
|
|
@ -16,9 +16,11 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
TEXT ·cpuidAsm(SB), 4, $0 // 4 = NOSPLIT
|
||||
MOVL eax_arg+0(FP), AX
|
||||
MOVL ecx_arg+4(FP), CX
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·cpuidAsm(SB), NOSPLIT, $0
|
||||
MOVL eaxArg+0(FP), AX
|
||||
MOVL ecxArg+4(FP), CX
|
||||
CPUID
|
||||
MOVL AX, eax+8(FP)
|
||||
MOVL BX, ebx+12(FP)
|
||||
|
|
|
@ -58,7 +58,7 @@ func TestUpdateNodeFeatures(t *testing.T) {
|
|||
fakeAnnotations := map[string]string{"version": version.Get()}
|
||||
fakeExtResources := ExtendedResources{"source-feature.1": "", "source-feature.2": ""}
|
||||
fakeFeatureLabelNames := make([]string, 0, len(fakeFeatureLabels))
|
||||
for k, _ := range fakeFeatureLabels {
|
||||
for k := range fakeFeatureLabels {
|
||||
fakeFeatureLabelNames = append(fakeFeatureLabelNames, k)
|
||||
}
|
||||
sort.Strings(fakeFeatureLabelNames)
|
||||
|
|
|
@ -105,7 +105,7 @@ func createStatusOp(verb string, resource string, path string, value string) sta
|
|||
}
|
||||
|
||||
// Create new NfdMaster server instance.
|
||||
func NewNfdMaster(args Args) (*nfdMaster, error) {
|
||||
func NewNfdMaster(args Args) (NfdMaster, error) {
|
||||
nfd := &nfdMaster{args: args, ready: make(chan bool, 1)}
|
||||
|
||||
// Check TLS related args
|
||||
|
@ -191,7 +191,7 @@ func (m *nfdMaster) WaitForReady(timeout time.Duration) bool {
|
|||
select {
|
||||
case ready, ok := <-m.ready:
|
||||
// Ready if the flag is true or the channel has been closed
|
||||
if ready == true || ok == false {
|
||||
if ready || !ok {
|
||||
return true
|
||||
}
|
||||
case <-time.After(timeout):
|
||||
|
|
|
@ -39,12 +39,10 @@ func TestDiscoveryWithMockSources(t *testing.T) {
|
|||
fakeFeatureNames := []string{"testfeature1", "testfeature2", "testfeature3"}
|
||||
fakeFeatures := source.Features{}
|
||||
fakeFeatureLabels := Labels{}
|
||||
fakeFeatureLabelNames := make([]string, 0, len(fakeFeatureNames))
|
||||
for _, f := range fakeFeatureNames {
|
||||
fakeFeatures[f] = true
|
||||
labelName := fakeFeatureSourceName + "-" + f
|
||||
fakeFeatureLabels[labelName] = "true"
|
||||
fakeFeatureLabelNames = append(fakeFeatureLabelNames, labelName)
|
||||
}
|
||||
fakeFeatureSource := source.FeatureSource(mockFeatureSource)
|
||||
|
||||
|
@ -89,7 +87,7 @@ func TestConfigParse(t *testing.T) {
|
|||
f, err := ioutil.TempFile("", "nfd-test-")
|
||||
defer os.Remove(f.Name())
|
||||
So(err, ShouldBeNil)
|
||||
f.WriteString(`sources:
|
||||
_, err = f.WriteString(`sources:
|
||||
kernel:
|
||||
configOpts:
|
||||
- "DMI"
|
||||
|
@ -97,6 +95,7 @@ func TestConfigParse(t *testing.T) {
|
|||
deviceClassWhitelist:
|
||||
- "ff"`)
|
||||
f.Close()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("When proper config file is given", func() {
|
||||
err := configParse(f.Name(), "")
|
||||
|
@ -208,7 +207,7 @@ func TestCreateFeatureLabels(t *testing.T) {
|
|||
|
||||
func TestGetFeatureLabels(t *testing.T) {
|
||||
Convey("When I get feature labels and panic occurs during discovery of a feature source", t, func() {
|
||||
fakePanicFeatureSource := source.FeatureSource(new(panic_fake.Source))
|
||||
fakePanicFeatureSource := source.FeatureSource(new(panicfake.Source))
|
||||
|
||||
returnedLabels, err := getFeatureLabels(fakePanicFeatureSource)
|
||||
Convey("No label is returned", func() {
|
||||
|
|
|
@ -60,7 +60,7 @@ var (
|
|||
// Global config
|
||||
type NFDConfig struct {
|
||||
Sources struct {
|
||||
Cpu *cpu.NFDConfig `json:"cpu,omitempty"`
|
||||
CPU *cpu.NFDConfig `json:"cpu,omitempty"`
|
||||
Kernel *kernel.NFDConfig `json:"kernel,omitempty"`
|
||||
Pci *pci.NFDConfig `json:"pci,omitempty"`
|
||||
Usb *usb.NFDConfig `json:"usb,omitempty"`
|
||||
|
@ -100,7 +100,7 @@ type nfdWorker struct {
|
|||
}
|
||||
|
||||
// Create new NfdWorker instance.
|
||||
func NewNfdWorker(args Args) (*nfdWorker, error) {
|
||||
func NewNfdWorker(args Args) (NfdWorker, error) {
|
||||
nfd := &nfdWorker{args: args}
|
||||
if args.SleepInterval > 0 && args.SleepInterval < time.Second {
|
||||
stderrLogger.Printf("WARNING: too short sleep-intervall specified (%s), forcing to 1s", args.SleepInterval.String())
|
||||
|
@ -188,7 +188,9 @@ func (w *nfdWorker) connect() error {
|
|||
}
|
||||
|
||||
// Dial and create a client
|
||||
dialOpts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTimeout(60 * time.Second)}
|
||||
dialCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
dialOpts := []grpc.DialOption{grpc.WithBlock()}
|
||||
if w.args.CaFile != "" || w.args.CertFile != "" || w.args.KeyFile != "" {
|
||||
// Load client cert for client authentication
|
||||
cert, err := tls.LoadX509KeyPair(w.args.CertFile, w.args.KeyFile)
|
||||
|
@ -214,7 +216,7 @@ func (w *nfdWorker) connect() error {
|
|||
} else {
|
||||
dialOpts = append(dialOpts, grpc.WithInsecure())
|
||||
}
|
||||
conn, err := grpc.Dial(w.args.Server, dialOpts...)
|
||||
conn, err := grpc.DialContext(dialCtx, w.args.Server, dialOpts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -235,7 +237,7 @@ func (w *nfdWorker) disconnect() {
|
|||
|
||||
// Parse configuration options
|
||||
func configParse(filepath string, overrides string) error {
|
||||
config.Sources.Cpu = &cpu.Config
|
||||
config.Sources.CPU = &cpu.Config
|
||||
config.Sources.Kernel = &kernel.Config
|
||||
config.Sources.Pci = &pci.Config
|
||||
config.Sources.Usb = &usb.Config
|
||||
|
@ -278,7 +280,7 @@ func configureParameters(sourcesWhiteList []string, labelWhiteListStr string) (e
|
|||
kernel.Source{},
|
||||
memory.Source{},
|
||||
network.Source{},
|
||||
panic_fake.Source{},
|
||||
panicfake.Source{},
|
||||
pci.Source{},
|
||||
storage.Source{},
|
||||
system.Source{},
|
||||
|
|
|
@ -26,17 +26,17 @@ import (
|
|||
|
||||
// Custom Features Configurations
|
||||
type MatchRule struct {
|
||||
PciId *rules.PciIdRule `json:"pciId,omitempty""`
|
||||
UsbId *rules.UsbIdRule `json:"usbId,omitempty""`
|
||||
LoadedKMod *rules.LoadedKModRule `json:"loadedKMod,omitempty""`
|
||||
PciID *rules.PciIDRule `json:"pciId,omitempty"`
|
||||
UsbID *rules.UsbIDRule `json:"usbId,omitempty"`
|
||||
LoadedKMod *rules.LoadedKModRule `json:"loadedKMod,omitempty"`
|
||||
}
|
||||
|
||||
type CustomFeature struct {
|
||||
type FeatureSpec struct {
|
||||
Name string `json:"name"`
|
||||
MatchOn []MatchRule `json:"matchOn"`
|
||||
}
|
||||
|
||||
type NFDConfig []CustomFeature
|
||||
type NFDConfig []FeatureSpec
|
||||
|
||||
var Config = NFDConfig{}
|
||||
|
||||
|
@ -66,11 +66,11 @@ func (s Source) Discover() (source.Features, error) {
|
|||
|
||||
// Process a single feature by Matching on the defined rules.
|
||||
// A feature is present if all defined Rules in a MatchRule return a match.
|
||||
func (s Source) discoverFeature(feature CustomFeature) (bool, error) {
|
||||
func (s Source) discoverFeature(feature FeatureSpec) (bool, error) {
|
||||
for _, rule := range feature.MatchOn {
|
||||
// PCI ID rule
|
||||
if rule.PciId != nil {
|
||||
match, err := rule.PciId.Match()
|
||||
if rule.PciID != nil {
|
||||
match, err := rule.PciID.Match()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -79,8 +79,8 @@ func (s Source) discoverFeature(feature CustomFeature) (bool, error) {
|
|||
}
|
||||
}
|
||||
// USB ID rule
|
||||
if rule.UsbId != nil {
|
||||
match, err := rule.UsbId.Match()
|
||||
if rule.UsbID != nil {
|
||||
match, err := rule.UsbID.Match()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -25,18 +25,18 @@ import (
|
|||
// each device attribute will be a list elements(strings).
|
||||
// Match operation: OR will be performed per element and AND will be performed per attribute.
|
||||
// An empty attribute will not be included in the matching process.
|
||||
type PciIdRuleInput struct {
|
||||
type PciIDRuleInput struct {
|
||||
Class []string `json:"class,omitempty"`
|
||||
Vendor []string `json:"vendor,omitempty"`
|
||||
Device []string `json:"device,omitempty"`
|
||||
}
|
||||
|
||||
type PciIdRule struct {
|
||||
PciIdRuleInput
|
||||
type PciIDRule struct {
|
||||
PciIDRuleInput
|
||||
}
|
||||
|
||||
// Match PCI devices on provided PCI device attributes
|
||||
func (r *PciIdRule) Match() (bool, error) {
|
||||
func (r *PciIDRule) Match() (bool, error) {
|
||||
devAttr := map[string]bool{}
|
||||
for _, attr := range []string{"class", "vendor", "device"} {
|
||||
devAttr[attr] = true
|
||||
|
@ -57,7 +57,7 @@ func (r *PciIdRule) Match() (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
func (r *PciIdRule) matchDevOnRule(dev pciutils.PciDeviceInfo) bool {
|
||||
func (r *PciIDRule) matchDevOnRule(dev pciutils.PciDeviceInfo) bool {
|
||||
if len(r.Class) == 0 && len(r.Vendor) == 0 && len(r.Device) == 0 {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -25,18 +25,18 @@ import (
|
|||
// each device attribute will be a list elements(strings).
|
||||
// Match operation: OR will be performed per element and AND will be performed per attribute.
|
||||
// An empty attribute will not be included in the matching process.
|
||||
type UsbIdRuleInput struct {
|
||||
type UsbIDRuleInput struct {
|
||||
Class []string `json:"class,omitempty"`
|
||||
Vendor []string `json:"vendor,omitempty"`
|
||||
Device []string `json:"device,omitempty"`
|
||||
}
|
||||
|
||||
type UsbIdRule struct {
|
||||
UsbIdRuleInput
|
||||
type UsbIDRule struct {
|
||||
UsbIDRuleInput
|
||||
}
|
||||
|
||||
// Match USB devices on provided USB device attributes
|
||||
func (r *UsbIdRule) Match() (bool, error) {
|
||||
func (r *UsbIDRule) Match() (bool, error) {
|
||||
devAttr := map[string]bool{}
|
||||
for _, attr := range []string{"class", "vendor", "device"} {
|
||||
devAttr[attr] = true
|
||||
|
@ -57,7 +57,7 @@ func (r *UsbIdRule) Match() (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
func (r *UsbIdRule) matchDevOnRule(dev usbutils.UsbDeviceInfo) bool {
|
||||
func (r *UsbIDRule) matchDevOnRule(dev usbutils.UsbDeviceInfo) bool {
|
||||
if len(r.Class) == 0 && len(r.Vendor) == 0 && len(r.Device) == 0 {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -22,19 +22,19 @@ import (
|
|||
|
||||
// getStaticFeatures returns statically configured custom features to discover
|
||||
// e.g RMDA related features. NFD configuration file may extend these custom features by adding rules.
|
||||
func getStaticFeatureConfig() []CustomFeature {
|
||||
return []CustomFeature{
|
||||
CustomFeature{
|
||||
func getStaticFeatureConfig() []FeatureSpec {
|
||||
return []FeatureSpec{
|
||||
FeatureSpec{
|
||||
Name: "rdma.capable",
|
||||
MatchOn: []MatchRule{
|
||||
MatchRule{
|
||||
PciId: &rules.PciIdRule{
|
||||
rules.PciIdRuleInput{Vendor: []string{"15b3"}},
|
||||
PciID: &rules.PciIDRule{
|
||||
PciIDRuleInput: rules.PciIDRuleInput{Vendor: []string{"15b3"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CustomFeature{
|
||||
FeatureSpec{
|
||||
Name: "rdma.available",
|
||||
MatchOn: []MatchRule{
|
||||
MatchRule{
|
||||
|
|
|
@ -56,9 +56,8 @@ func readPciDevInfo(devPath string, deviceAttrSpec map[string]bool) (PciDeviceIn
|
|||
if err != nil {
|
||||
if must {
|
||||
return info, fmt.Errorf("Failed to read device %s: %s", attr, err)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
continue
|
||||
|
||||
}
|
||||
info[attr] = attrVal
|
||||
|
|
|
@ -60,7 +60,7 @@ func readUsbDevInfo(devPath string, deviceAttrSpec map[string]bool) (UsbClassMap
|
|||
classmap := UsbClassMap{}
|
||||
info := UsbDeviceInfo{}
|
||||
|
||||
for attr, _ := range deviceAttrSpec {
|
||||
for attr := range deviceAttrSpec {
|
||||
attrVal, _ := readSingleUsbAttribute(devPath, attr)
|
||||
if len(attrVal) > 0 {
|
||||
info[attr] = attrVal
|
||||
|
|
|
@ -140,7 +140,7 @@ func readKconfigGzip(filename string) ([]byte, error) {
|
|||
func parseKconfig() (map[string]string, error) {
|
||||
kconfig := map[string]string{}
|
||||
raw := []byte(nil)
|
||||
err := error(nil)
|
||||
var err error
|
||||
|
||||
// First, try kconfig specified in the config file
|
||||
if len(Config.KconfigFile) > 0 {
|
||||
|
|
|
@ -43,12 +43,12 @@ func (s Source) Name() string { return "local" }
|
|||
func (s Source) Discover() (source.Features, error) {
|
||||
featuresFromHooks, err := getFeaturesFromHooks()
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
log.Printf("%v", err)
|
||||
}
|
||||
|
||||
featuresFromFiles, err := getFeaturesFromFiles()
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
log.Printf("%v", err)
|
||||
}
|
||||
|
||||
// Merge features from hooks and files
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package panic_fake
|
||||
package panicfake
|
||||
|
||||
import "sigs.k8s.io/node-feature-discovery/source"
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ type FeatureValue interface {
|
|||
type BoolFeatureValue bool
|
||||
|
||||
func (b BoolFeatureValue) String() string {
|
||||
if b == true {
|
||||
if b {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
|
|
|
@ -34,8 +34,8 @@ import (
|
|||
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
|
||||
master "sigs.k8s.io/node-feature-discovery/pkg/nfd-master"
|
||||
)
|
||||
|
@ -44,7 +44,6 @@ var (
|
|||
dockerRepo = flag.String("nfd.repo", "quay.io/kubernetes_incubator/node-feature-discovery", "Docker repository to fetch image from")
|
||||
dockerTag = flag.String("nfd.tag", "e2e-test", "Docker tag to use")
|
||||
e2eConfigFile = flag.String("nfd.e2e-config", "", "Configuration parameters for end-to-end tests")
|
||||
labelPrefix = "feature.node.kubernetes.io/"
|
||||
|
||||
conf *e2eConfig
|
||||
)
|
||||
|
@ -87,13 +86,13 @@ func readConfig() {
|
|||
return
|
||||
}
|
||||
|
||||
By("Reading end-to-end test configuration file")
|
||||
ginkgo.By("Reading end-to-end test configuration file")
|
||||
data, err := ioutil.ReadFile(*e2eConfigFile)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By("Parsing end-to-end test configuration data")
|
||||
ginkgo.By("Parsing end-to-end test configuration data")
|
||||
err = yaml.Unmarshal(data, &conf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
}
|
||||
|
||||
// Create required RBAC configuration
|
||||
|
@ -364,14 +363,14 @@ func newHostPathType(typ v1.HostPathType) *v1.HostPathType {
|
|||
// labels and annotations
|
||||
func cleanupNode(cs clientset.Interface) {
|
||||
nodeList, err := cs.CoreV1().Nodes().List(metav1.ListOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
for _, n := range nodeList.Items {
|
||||
var err error
|
||||
var node *v1.Node
|
||||
for retry := 0; retry < 5; retry++ {
|
||||
node, err = cs.CoreV1().Nodes().Get(n.Name, metav1.GetOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
update := false
|
||||
// Remove labels
|
||||
|
@ -390,11 +389,11 @@ func cleanupNode(cs clientset.Interface) {
|
|||
}
|
||||
}
|
||||
|
||||
if update == false {
|
||||
if !update {
|
||||
break
|
||||
}
|
||||
|
||||
By("Deleting NFD labels and annotations from node " + node.Name)
|
||||
ginkgo.By("Deleting NFD labels and annotations from node " + node.Name)
|
||||
_, err = cs.CoreV1().Nodes().Update(node)
|
||||
if err != nil {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
@ -403,7 +402,7 @@ func cleanupNode(cs clientset.Interface) {
|
|||
}
|
||||
|
||||
}
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,42 +410,42 @@ func cleanupNode(cs clientset.Interface) {
|
|||
var _ = framework.KubeDescribe("Node Feature Discovery", func() {
|
||||
f := framework.NewDefaultFramework("node-feature-discovery")
|
||||
|
||||
Context("when deploying a single nfd-master pod", func() {
|
||||
ginkgo.Context("when deploying a single nfd-master pod", func() {
|
||||
var masterPod *v1.Pod
|
||||
|
||||
BeforeEach(func() {
|
||||
ginkgo.BeforeEach(func() {
|
||||
err := configureRBAC(f.ClientSet, f.Namespace.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
// Launch nfd-master
|
||||
By("Creating nfd master pod and nfd-master service")
|
||||
ginkgo.By("Creating nfd master pod and nfd-master service")
|
||||
image := fmt.Sprintf("%s:%s", *dockerRepo, *dockerTag)
|
||||
masterPod = nfdMasterPod(image, false)
|
||||
masterPod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(masterPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
// Create nfd-master service
|
||||
nfdSvc, err := createService(f.ClientSet, f.Namespace.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By("Waiting for the nfd-master pod to be running")
|
||||
Expect(e2epod.WaitForPodRunningInNamespace(f.ClientSet, masterPod)).NotTo(HaveOccurred())
|
||||
ginkgo.By("Waiting for the nfd-master pod to be running")
|
||||
gomega.Expect(e2epod.WaitForPodRunningInNamespace(f.ClientSet, masterPod)).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By("Waiting for the nfd-master service to be up")
|
||||
Expect(framework.WaitForService(f.ClientSet, f.Namespace.Name, nfdSvc.ObjectMeta.Name, true, time.Second, 10*time.Second)).NotTo(HaveOccurred())
|
||||
ginkgo.By("Waiting for the nfd-master service to be up")
|
||||
gomega.Expect(framework.WaitForService(f.ClientSet, f.Namespace.Name, nfdSvc.ObjectMeta.Name, true, time.Second, 10*time.Second)).NotTo(gomega.HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
ginkgo.AfterEach(func() {
|
||||
err := deconfigureRBAC(f.ClientSet, f.Namespace.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
})
|
||||
|
||||
//
|
||||
// Simple test with only the fake source enabled
|
||||
//
|
||||
Context("and a single worker pod with fake source enabled", func() {
|
||||
It("it should decorate the node with the fake feature labels", func() {
|
||||
ginkgo.Context("and a single worker pod with fake source enabled", func() {
|
||||
ginkgo.It("it should decorate the node with the fake feature labels", func() {
|
||||
|
||||
fakeFeatureLabels := map[string]string{
|
||||
master.LabelNs + "fake-fakefeature1": "true",
|
||||
|
@ -458,32 +457,34 @@ var _ = framework.KubeDescribe("Node Feature Discovery", func() {
|
|||
cleanupNode(f.ClientSet)
|
||||
|
||||
// Launch nfd-worker
|
||||
By("Creating a nfd worker pod")
|
||||
ginkgo.By("Creating a nfd worker pod")
|
||||
image := fmt.Sprintf("%s:%s", *dockerRepo, *dockerTag)
|
||||
workerPod := nfdWorkerPod(image, []string{"--oneshot", "--sources=fake"})
|
||||
workerPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(workerPod)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By("Waiting for the nfd-worker pod to succeed")
|
||||
Expect(e2epod.WaitForPodSuccessInNamespace(f.ClientSet, workerPod.ObjectMeta.Name, f.Namespace.Name)).NotTo(HaveOccurred())
|
||||
ginkgo.By("Waiting for the nfd-worker pod to succeed")
|
||||
gomega.Expect(e2epod.WaitForPodSuccessInNamespace(f.ClientSet, workerPod.ObjectMeta.Name, f.Namespace.Name)).NotTo(gomega.HaveOccurred())
|
||||
workerPod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(workerPod.ObjectMeta.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By(fmt.Sprintf("Making sure '%s' was decorated with the fake feature labels", workerPod.Spec.NodeName))
|
||||
ginkgo.By(fmt.Sprintf("Making sure '%s' was decorated with the fake feature labels", workerPod.Spec.NodeName))
|
||||
node, err := f.ClientSet.CoreV1().Nodes().Get(workerPod.Spec.NodeName, metav1.GetOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
for k, v := range fakeFeatureLabels {
|
||||
Expect(node.Labels[k]).To(Equal(v))
|
||||
gomega.Expect(node.Labels[k]).To(gomega.Equal(v))
|
||||
}
|
||||
|
||||
// Check that there are no unexpected NFD labels
|
||||
for k := range node.Labels {
|
||||
if strings.HasPrefix(k, master.LabelNs) {
|
||||
Expect(fakeFeatureLabels).Should(HaveKey(k))
|
||||
gomega.Expect(fakeFeatureLabels).Should(gomega.HaveKey(k))
|
||||
}
|
||||
}
|
||||
|
||||
By("Deleting the node-feature-discovery worker pod")
|
||||
ginkgo.By("Deleting the node-feature-discovery worker pod")
|
||||
err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(workerPod.ObjectMeta.Name, &metav1.DeleteOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
cleanupNode(f.ClientSet)
|
||||
})
|
||||
|
@ -492,31 +493,31 @@ var _ = framework.KubeDescribe("Node Feature Discovery", func() {
|
|||
//
|
||||
// More comprehensive test when --e2e-node-config is enabled
|
||||
//
|
||||
Context("and nfd-workers as a daemonset with default sources enabled", func() {
|
||||
It("the node labels listed in the e2e config should be present", func() {
|
||||
ginkgo.Context("and nfd-workers as a daemonset with default sources enabled", func() {
|
||||
ginkgo.It("the node labels listed in the e2e config should be present", func() {
|
||||
readConfig()
|
||||
if conf == nil {
|
||||
Skip("no e2e-config was specified")
|
||||
ginkgo.Skip("no e2e-config was specified")
|
||||
}
|
||||
if conf.DefaultFeatures == nil {
|
||||
Skip("no 'defaultFeatures' specified in e2e-config")
|
||||
ginkgo.Skip("no 'defaultFeatures' specified in e2e-config")
|
||||
}
|
||||
fConf := conf.DefaultFeatures
|
||||
|
||||
// Remove pre-existing stale annotations and labels
|
||||
cleanupNode(f.ClientSet)
|
||||
|
||||
By("Creating nfd-worker daemonset")
|
||||
ginkgo.By("Creating nfd-worker daemonset")
|
||||
workerDS := nfdWorkerDaemonSet(fmt.Sprintf("%s:%s", *dockerRepo, *dockerTag), []string{})
|
||||
workerDS, err := f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(workerDS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By("Waiting for daemonset pods to be ready")
|
||||
Expect(e2epod.WaitForPodsReady(f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 5)).NotTo(HaveOccurred())
|
||||
ginkgo.By("Waiting for daemonset pods to be ready")
|
||||
gomega.Expect(e2epod.WaitForPodsReady(f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 5)).NotTo(gomega.HaveOccurred())
|
||||
|
||||
By("Getting node objects")
|
||||
ginkgo.By("Getting node objects")
|
||||
nodeList, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
for _, node := range nodeList.Items {
|
||||
if _, ok := fConf.Nodes[node.Name]; !ok {
|
||||
|
@ -528,10 +529,10 @@ var _ = framework.KubeDescribe("Node Feature Discovery", func() {
|
|||
|
||||
// Check labels
|
||||
for k, v := range nodeConf.ExpectedLabelValues {
|
||||
Expect(node.Labels).To(HaveKeyWithValue(k, v))
|
||||
gomega.Expect(node.Labels).To(gomega.HaveKeyWithValue(k, v))
|
||||
}
|
||||
for k := range nodeConf.ExpectedLabelKeys {
|
||||
Expect(node.Labels).To(HaveKey(k))
|
||||
gomega.Expect(node.Labels).To(gomega.HaveKey(k))
|
||||
}
|
||||
for k := range node.Labels {
|
||||
if strings.HasPrefix(k, master.LabelNs) {
|
||||
|
@ -542,16 +543,16 @@ var _ = framework.KubeDescribe("Node Feature Discovery", func() {
|
|||
continue
|
||||
}
|
||||
// Ignore if the label key was not whitelisted
|
||||
Expect(fConf.LabelWhitelist).NotTo(HaveKey(k))
|
||||
gomega.Expect(fConf.LabelWhitelist).NotTo(gomega.HaveKey(k))
|
||||
}
|
||||
}
|
||||
|
||||
// Check annotations
|
||||
for k, v := range nodeConf.ExpectedAnnotationValues {
|
||||
Expect(node.Annotations).To(HaveKeyWithValue(k, v))
|
||||
gomega.Expect(node.Annotations).To(gomega.HaveKeyWithValue(k, v))
|
||||
}
|
||||
for k := range nodeConf.ExpectedAnnotationKeys {
|
||||
Expect(node.Annotations).To(HaveKey(k))
|
||||
gomega.Expect(node.Annotations).To(gomega.HaveKey(k))
|
||||
}
|
||||
for k := range node.Annotations {
|
||||
if strings.HasPrefix(k, master.AnnotationNs) {
|
||||
|
@ -562,18 +563,19 @@ var _ = framework.KubeDescribe("Node Feature Discovery", func() {
|
|||
continue
|
||||
}
|
||||
// Ignore if the annotation was not whitelisted
|
||||
Expect(fConf.AnnotationWhitelist).NotTo(HaveKey(k))
|
||||
gomega.Expect(fConf.AnnotationWhitelist).NotTo(gomega.HaveKey(k))
|
||||
}
|
||||
}
|
||||
|
||||
// Node running nfd-master should have master version annotation
|
||||
if node.Name == masterPod.Spec.NodeName {
|
||||
Expect(node.Annotations).To(HaveKey(master.AnnotationNs + "master.version"))
|
||||
gomega.Expect(node.Annotations).To(gomega.HaveKey(master.AnnotationNs + "master.version"))
|
||||
}
|
||||
}
|
||||
|
||||
By("Deleting nfd-worker daemonset")
|
||||
ginkgo.By("Deleting nfd-worker daemonset")
|
||||
err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Delete(workerDS.ObjectMeta.Name, &metav1.DeleteOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
cleanupNode(f.ClientSet)
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue