fix: occasional panic when watched YAML files change (#1246)

<!-- Please use this template for your pull request. -->
<!-- Please use the sections that you need and delete other sections -->

## This PR
At the moment, the yamlToJSON will convert `[]byte("")` to `"null"`.
While "null" is a normal string, it will bypass all validator and lead
to panic.
### Related Issues
<!-- add here the GitHub issue that this PR resolves if applicable -->

Fixes [#1242](https://github.com/open-feature/flagd/issues/1242)

### Notes
I found that sometime, the os.Readfile will return empty byte and no
error, this will cause the yamlToJSON convert the rawData ("") to
jsonData ("null").
Moreover, when I check the log, the watcher is reading file content a
lot at a times for checking file changes, so it could be the reason why
os.Readfile return empty byte?

![image](https://github.com/open-feature/flagd/assets/20945393/75b68be0-eba4-4f96-b5ee-5f4f383bae5c)
### Follow-up Tasks
I think we have to check the behavior of os.Readfile?

### How to test
<!-- if applicable, add testing instructions under this section -->

Signed-off-by: Tran Dinh Loc <dinhlockt02@gmail.com>
This commit is contained in:
DinhLocTran 2024-03-13 02:47:37 +07:00 committed by GitHub
parent 7afdc0cda4
commit 6249d12ec4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 0 deletions

View File

@ -171,6 +171,10 @@ func (fs *Sync) fetch(_ context.Context) (string, error) {
// yamlToJSON is a generic helper function to convert
// yaml to json
func yamlToJSON(rawFile []byte) (string, error) {
if len(rawFile) == 0 {
return "", nil
}
var ms map[string]interface{}
// yaml.Unmarshal unmarshals to map[interface]interface{}
if err := yaml.Unmarshal(rawFile, &ms); err != nil {

View File

@ -309,3 +309,31 @@ func writeToFile(t *testing.T, fetchDirName, fileContents string) {
t.Fatal(err)
}
}
func TestFilePathSync_yamlToJSON(t *testing.T) {
tests := map[string]struct {
input []byte
handleResponse func(t *testing.T, output string, err error)
}{
"empty": {
input: []byte(""),
handleResponse: func(t *testing.T, output string, err error) {
if err != nil {
t.Fatalf("expect no err, got err = %v", err)
}
if output != "" {
t.Fatalf("expect output = '', got output = '%v'", output)
}
},
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
output, err := yamlToJSON(tt.input)
tt.handleResponse(t, output, err)
})
}
}