1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2024-12-15 17:50:49 +00:00

Merge pull request #1285 from AhmedGrati/feat-add-expiry-date-feature-files

Feat: add expiry date for feature files
This commit is contained in:
Kubernetes Prow Robot 2023-09-05 02:19:50 -07:00 committed by GitHub
commit 0b218a1eca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 160 additions and 4 deletions

View file

@ -317,6 +317,38 @@ Label namespace may be specified with `<namespace>/<name>[=<value>]`.
Comment lines (starting with `#`) are ignored.
Adding following line anywhere to feature file defines date when
its content expires / is ignored:
```plaintext
# +expiry-time=2023-07-29T11:22:33Z
```
Also, the expiry-time value would stay the same during the processing of the
feature file until another expiry-time directive is encountered.
Considering the following file:
```plaintext
# +expiry-time=2012-07-28T11:22:33Z
featureKey=featureValue
# +expiry-time=2080-07-28T11:22:33Z
featureKey2=featureValue2
# +expiry-time=2070-07-28T11:22:33Z
featureKey3=featureValue3
# +expiry-time=2002-07-28T11:22:33Z
featureKey4=featureValue4
```
After processing the above file, only `featureKey2` and `featureKey3` would be
included in the list of accepted features.
> **NOTE:** The time format that we are supporting is RFC3339. Also, the `expiry-time`
> tag is only evaluated in each re-discovery period, and the expiration of
> node labels is not tracked.
### Mounts
The standard NFD deployments contain `hostPath` mounts for

View file

@ -23,6 +23,7 @@ import (
"os/exec"
"path/filepath"
"strings"
"time"
"k8s.io/klog/v2"
@ -37,6 +38,13 @@ const Name = "local"
// LabelFeature of this feature source
const LabelFeature = "label"
// ExpiryTimeKey is the key of this feature source indicating
// when features should be removed.
const ExpiryTimeKey = "expiry-time"
// DirectivePrefix defines the prefix of directives that should be parsed
const DirectivePrefix = "# +"
// Config
var (
featureFilesDir = "/etc/kubernetes/node-feature-discovery/features.d/"
@ -53,6 +61,11 @@ type Config struct {
HooksEnabled bool `json:"hooksEnabled,omitempty"`
}
// parsingOpts contains options used for directives parsing
type parsingOpts struct {
ExpiryTime time.Time
}
// Singleton source instance
var (
src = localSource{config: newDefaultConfig()}
@ -144,14 +157,56 @@ func (s *localSource) GetFeatures() *nfdv1alpha1.Features {
return s.features
}
func parseFeatures(lines [][]byte) map[string]string {
func parseDirectives(line string, opts *parsingOpts) error {
if !strings.HasPrefix(line, DirectivePrefix) {
return nil
}
directive := line[len(DirectivePrefix):]
split := strings.SplitN(directive, "=", 2)
key := split[0]
if len(split) == 1 {
return fmt.Errorf("invalid directive format in %q, should be '# +key=value'", line)
}
value := split[1]
switch key {
case ExpiryTimeKey:
expiryDate, err := time.Parse(time.RFC3339, strings.TrimSpace(value))
if err != nil {
return fmt.Errorf("failed to parse expiry-date directive: %w", err)
}
opts.ExpiryTime = expiryDate
default:
return fmt.Errorf("unknown feature file directive %q", key)
}
return nil
}
func parseFeatures(lines [][]byte, fileName string) map[string]string {
features := make(map[string]string)
now := time.Now()
parsingOpts := &parsingOpts{
ExpiryTime: now,
}
for _, l := range lines {
line := strings.TrimSpace(string(l))
if len(line) > 0 {
// Skip comment lines
if strings.HasPrefix(line, "#") {
// Parse directives
err := parseDirectives(line, parsingOpts)
if err != nil {
klog.ErrorS(err, "error while parsing directives", "fileName", fileName)
}
continue
}
// handle expiration
if parsingOpts.ExpiryTime.Before(now) {
continue
}
@ -197,7 +252,7 @@ func getFeaturesFromHooks() (map[string]string, error) {
}
// Append features
fileFeatures := parseFeatures(lines)
fileFeatures := parseFeatures(lines, fileName)
klog.V(4).InfoS("hook executed", "fileName", fileName, "features", utils.DelayedDumper(fileFeatures))
for k, v := range fileFeatures {
if old, ok := features[k]; ok {
@ -273,7 +328,8 @@ func getFeaturesFromFiles() (map[string]string, error) {
}
// Append features
fileFeatures := parseFeatures(lines)
fileFeatures := parseFeatures(lines, fileName)
klog.V(4).InfoS("feature file read", "fileName", fileName, "features", utils.DelayedDumper(fileFeatures))
for k, v := range fileFeatures {
if old, ok := features[k]; ok {

View file

@ -17,7 +17,11 @@ limitations under the License.
package local
import (
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@ -33,3 +37,48 @@ func TestLocalSource(t *testing.T) {
assert.Empty(t, l)
}
func TestGetExpirationDate(t *testing.T) {
expectedFeaturesLen := 5
pwd, _ := os.Getwd()
featureFilesDir = filepath.Join(pwd, "testdata/features.d")
features, err := getFeaturesFromFiles()
fmt.Println(features)
assert.NoError(t, err)
assert.Equal(t, expectedFeaturesLen, len(features))
}
func TestParseDirectives(t *testing.T) {
testCases := []struct {
name string
directive string
wantErr bool
}{
{
name: "valid directive",
directive: "# +expiry-time=2080-07-28T11:22:33Z",
wantErr: false,
},
{
name: "invalid directive",
directive: "# +random-key=random-value",
wantErr: true,
},
{
name: "invalid directive format",
directive: "# + Something",
wantErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
parsingOpts := parsingOpts{
ExpiryTime: time.Now(),
}
err := parseDirectives(tc.directive, &parsingOpts)
assert.Equal(t, err != nil, tc.wantErr)
})
}
}

View file

@ -0,0 +1,2 @@
# +expiry-time=2012-07-28T11:22:33Z
featureKeyExpired=featureValue

View file

@ -0,0 +1,2 @@
# Notes: foo bar
featureKeyRandomComment=featureValue

View file

@ -0,0 +1,11 @@
# +expiry-time=2012-07-28T11:22:33Z
featureKey=featureValue
# +expiry-time=2080-07-28T11:22:33Z
featureKey2=featureValue2
# +expiry-time=2070-07-28T11:22:33Z
featureKey3=featureValue3
# +expiry-time=2002-07-28T11:22:33Z
featureKey4=featureValue4

View file

@ -0,0 +1,2 @@
# +expiry-time=2080-07-28T11:22:33X
featureKeyUnparsable=featureValue

View file

@ -0,0 +1,2 @@
# +expiry-time=2080-07-28T11:22:33Z
featureKeyValid=featureValue