diff --git a/docs/usage/customization-guide.md b/docs/usage/customization-guide.md index bf641587a1..e277233826 100644 --- a/docs/usage/customization-guide.md +++ b/docs/usage/customization-guide.md @@ -313,12 +313,16 @@ The label value defaults to `true`, if not specified. Label namespace may be specified with `/[=]`. -You can include the following block if you want to define the expiration date +You can include the following block if you want to define the expiration date of features that are described in the feature files: + ```plaintext -# +expiry-time: 2023-07-29T11:22:33Z +# +expiry-time=2023-07-29T11:22:33Z ``` -**Note: The time format that we are supporting is RFC3339.** + +**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 diff --git a/source/local/local.go b/source/local/local.go index 99f8608c7e..cf466f28a3 100644 --- a/source/local/local.go +++ b/source/local/local.go @@ -149,7 +149,7 @@ func (s *localSource) GetFeatures() *nfdv1alpha1.Features { return s.features } -func parseFeatures(lines [][]byte) map[string]string { +func parseFeatures(lines [][]byte, fileName string) map[string]string { features := make(map[string]string) for _, line := range lines { @@ -162,7 +162,21 @@ func parseFeatures(lines [][]byte) map[string]string { if len(lineSplit) == 1 { features[key] = "true" } else { - features[key] = lineSplit[1] + value := lineSplit[1] + switch key { + case ExpiryDateKey: + expiryDate, err := time.Parse(time.RFC3339, strings.TrimSpace(value)) + if err != nil { + klog.ErrorS(err, "failed to parse feature file expiry date", "fileName", fileName) + continue + } + if expiryDate.Before(time.Now()) { + klog.InfoS("feature file is expired", "fileName", fileName) + return map[string]string{} + } + default: + features[key] = value + } } } } @@ -196,7 +210,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 { @@ -272,18 +286,7 @@ func getFeaturesFromFiles() (map[string]string, error) { } // Append features - fileFeatures := parseFeatures(lines) - - // Check expiration of file features - expiryDate, err := getExpirationDate(lines) - if err != nil { - klog.ErrorS(err, "failed to parse feature file expiry date", "fileName", fileName) - continue - } - - if expiryDate.Before(time.Now()) { - continue - } + fileFeatures := parseFeatures(lines, fileName) klog.V(4).InfoS("feature file read", "fileName", fileName, "features", utils.DelayedDumper(fileFeatures)) for k, v := range fileFeatures { @@ -297,27 +300,6 @@ func getFeaturesFromFiles() (map[string]string, error) { return features, nil } -// Return the expiration date of a feature file -func getExpirationDate(lines [][]byte) (time.Time, error) { - for _, line := range lines { - if len(line) > 0 { - lineSplit := strings.SplitN(string(line), ":", 2) - - key := lineSplit[0] - - if key == ExpiryDateKey { - expiryDate, err := time.Parse(time.RFC3339, lineSplit[1]) - if err != nil { - return time.Now(), err - } - return expiryDate, nil - } - } - } - - return time.Now(), nil -} - // Read one file func getFileContent(fileName string) ([][]byte, error) { var lines [][]byte diff --git a/source/local/local_test.go b/source/local/local_test.go index e83493c63c..70ae5b9d90 100644 --- a/source/local/local_test.go +++ b/source/local/local_test.go @@ -17,6 +17,7 @@ limitations under the License. package local import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -33,3 +34,45 @@ func TestLocalSource(t *testing.T) { assert.Empty(t, l) } + +func TestGetExpirationDate(t *testing.T) { + + testCases := []struct { + name string + expiryDate string + expectedFeaturesLen int + }{ + { + name: "valid feature file", + expiryDate: "2080-07-28T11:22:33Z", + expectedFeaturesLen: 1, + }, + { + name: "expired feature file", + expiryDate: "2012-07-28T11:22:33Z", + expectedFeaturesLen: 0, + }, + { + name: "unparsable expiryDate", + expiryDate: "2080-07-28T11:22:33X", + expectedFeaturesLen: 1, + }, + } + + for _, tc := range testCases { + fileContent := []string{ + fmt.Sprintf("# +expiry-time=%v", tc.expiryDate), + "featureKey=featureValue", + } + + fileContentByte := [][]byte{} + + for _, content := range fileContent { + fileContentByte = append(fileContentByte, []byte(content)) + } + + features := parseFeatures(fileContentByte, "testfile") + assert.Equal(t, tc.expectedFeaturesLen, len(features)) + + } +}