1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2024-12-14 11:57:51 +00:00
node-feature-discovery/pkg/kubectl-nfd/dryrun.go
Carlos Eduardo Arango Gutierrez 3434557d7c
Move NFD api to a separate go mod
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
2024-04-05 16:35:47 +02:00

195 lines
5.3 KiB
Go

/*
Copyright 2023 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 kubectlnfd
import (
"fmt"
"os"
"strings"
"sigs.k8s.io/yaml"
corev1 "k8s.io/api/core/v1"
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
"sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/nodefeaturerule"
"sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/validate"
)
func DryRun(nodefeaturerulepath, nodefeaturepath string) []error {
var errs []error
nfr := nfdv1alpha1.NodeFeatureRule{}
nf := nfdv1alpha1.NodeFeature{}
nfrFile, err := os.ReadFile(nodefeaturerulepath)
if err != nil {
return []error{fmt.Errorf("error reading NodeFeatureRule file: %w", err)}
}
err = yaml.Unmarshal(nfrFile, &nfr)
if err != nil {
return []error{fmt.Errorf("error parsing NodeFeatureRule: %w", err)}
}
nfFile, err := os.ReadFile(nodefeaturepath)
if err != nil {
return []error{fmt.Errorf("error reading NodeFeatureRule file: %w", err)}
}
err = yaml.Unmarshal(nfFile, &nf)
if err != nil {
return []error{fmt.Errorf("error parsing NodeFeatureRule: %w", err)}
}
errs = append(errs, processNodeFeatureRule(nfr, nf.Spec)...)
return errs
}
func processNodeFeatureRule(nodeFeatureRule nfdv1alpha1.NodeFeatureRule, nodeFeature nfdv1alpha1.NodeFeatureSpec) []error {
var errs []error
var taints []corev1.Taint
extendedResources := make(map[string]string)
labels := make(map[string]string)
annotations := make(map[string]string)
for _, rule := range nodeFeatureRule.Spec.Rules {
fmt.Println("Processing rule: ", rule.Name)
ruleOut, err := nodefeaturerule.Execute(&rule, &nodeFeature.Features)
if err != nil {
errs = append(errs, fmt.Errorf("failed to process rule: %q - %w", rule.Name, err))
continue
}
// taints
taints = append(taints, ruleOut.Taints...)
// labels
for k, v := range ruleOut.Labels {
// Dynamic Value
if strings.HasPrefix(v, "@") {
dvalue, err := getDynamicValue(v, &nodeFeature.Features)
if err != nil {
errs = append(errs, fmt.Errorf("failed to get dynamic value for label %q: %w", k, err))
continue
}
labels[k] = dvalue
continue
}
labels[k] = v
}
// extended resources
for k, v := range ruleOut.ExtendedResources {
// Dynamic Value
if strings.HasPrefix(v, "@") {
dvalue, err := getDynamicValue(v, &nodeFeature.Features)
if err != nil {
errs = append(errs, fmt.Errorf("failed to get dynamic value for extendedResource %q: %w", k, err))
continue
}
extendedResources[k] = dvalue
continue
}
extendedResources[k] = v
}
// annotations
for k, v := range ruleOut.Annotations {
annotations[k] = v
}
}
if len(taints) > 0 {
taintValidation := validate.Taints(taints)
fmt.Println("***\tTaints\t***")
for _, taint := range taints {
fmt.Println(taint)
}
if len(taintValidation) > 0 {
fmt.Println("\t-Validation errors-")
for _, err := range taintValidation {
fmt.Println(err)
}
}
}
if len(labels) > 0 {
labelValidation := validate.Labels(labels)
fmt.Println("***\tLabels\t***")
for k, v := range labels {
fmt.Printf("%s=%s\n", k, v)
}
if len(labelValidation) > 0 {
fmt.Println("\t-Validation errors-")
for _, err := range labelValidation {
fmt.Println(err)
}
}
}
if len(extendedResources) > 0 {
resourceValidation := processExtendedResources(extendedResources, nodeFeature)
fmt.Println("***\tExtended Resources\t***")
for k, v := range extendedResources {
fmt.Printf("%s=%s\n", k, v)
}
if len(resourceValidation) > 0 {
fmt.Println("\t-Validation errors-")
for _, err := range resourceValidation {
fmt.Println(err)
}
}
}
if len(annotations) > 0 {
annotationsValidation := validate.Annotations(annotations)
fmt.Println("***\tAnnotations\t***")
for k, v := range annotations {
fmt.Printf("%s=%s\n", k, v)
}
if len(annotationsValidation) > 0 {
fmt.Println("\t-Validation errors-")
for _, err := range annotationsValidation {
fmt.Println(err)
}
}
}
return errs
}
func processExtendedResources(extendedResources map[string]string, nodeFeature nfdv1alpha1.NodeFeatureSpec) []error {
var errs []error
return append(errs, validate.ExtendedResources(extendedResources)...)
}
func getDynamicValue(value string, features *nfdv1alpha1.Features) (string, error) {
// value is a string in the form of attribute.featureset.elements
split := strings.SplitN(value[1:], ".", 3)
if len(split) != 3 {
return "", fmt.Errorf("value %s is not in the form of '@domain.feature.element'", value)
}
featureName := split[0] + "." + split[1]
elementName := split[2]
attrFeatureSet, ok := features.Attributes[featureName]
if !ok {
return "", fmt.Errorf("feature %s not found", featureName)
}
element, ok := attrFeatureSet.Elements[elementName]
if !ok {
return "", fmt.Errorf("element %s not found on feature %s", elementName, featureName)
}
return element, nil
}