Skip to content

Commit

Permalink
[nad] Add GetJSONPathFromConfig
Browse files Browse the repository at this point in the history
Adds function to return the result of the jsonPath as string from
the NetworkAttachmentDefinition config. If the NAD has no config,
an empty string is returned.
The jsonPath must be in the format e.g. ".ipam"

Signed-off-by: Martin Schuppert <[email protected]>
  • Loading branch information
stuggi committed Dec 11, 2024
1 parent 6dc9fd0 commit d5ff7fa
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 0 deletions.
34 changes: 34 additions & 0 deletions modules/common/networkattachment/networkattachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,37 @@ func EnsureNetworksAnnotation(

return annotationString, nil
}

// GetJSONPathFromConfig - returns the result of the jsonPath as string
// from the NetworkAttachmentDefinition config.
// if the NAD has no config, an empty string is returned.
// The jsonPath must be in the format e.g. ".ipam"
func GetJSONPathFromConfig(netAtt networkv1.NetworkAttachmentDefinition, path string) (string, error) {
var data interface{}
buf := new(bytes.Buffer)

if netAtt.Spec.Config == "" {
return buf.String(), nil
}

if err := json.Unmarshal([]byte(netAtt.Spec.Config), &data); err != nil {
return "", fmt.Errorf("failed to unmarshal JSON data: %w", err)
}

// use jsonpath to parse the cni config
jp := jsonpath.New(netAtt.Name)

// Parse the JSONPath template to get the ipam
err := jp.Parse(fmt.Sprintf(`{.%s}`, path))
if err != nil {
return "", fmt.Errorf("parse template error: %w", err)
}

// get the ipam from the config
err = jp.Execute(buf, data)
if err != nil {
return "", fmt.Errorf("parse execute template against nad %+v error: %w", netAtt.Spec.Config, err)
}

return buf.String(), nil
}
76 changes: 76 additions & 0 deletions modules/common/networkattachment/networkattachment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,79 @@ func TestEnsureNetworksAnnotation(t *testing.T) {
})
}
}

func TestGetJSONPathFromConfig(t *testing.T) {

tests := []struct {
name string
nad networkv1.NetworkAttachmentDefinition
path string
want string
}{
{
name: "No config",
nad: networkv1.NetworkAttachmentDefinition{},
path: ".ipam",
want: "",
},
{
name: "get .name",
nad: networkv1.NetworkAttachmentDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "one", Namespace: "foo"},
Spec: networkv1.NetworkAttachmentDefinitionSpec{
Config: `
{
"cniVersion": "0.3.1",
"name": "internalapi",
"type": "macvlan",
"master": "internalapi",
"ipam": {
"type": "whereabouts",
"range": "172.17.0.0/24",
"range_start": "172.17.0.30",
"range_end": "172.17.0.70"
}
}
`,
},
},
path: ".name",
want: "internalapi",
},
{
name: "get .ipam.range",
nad: networkv1.NetworkAttachmentDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "one", Namespace: "foo"},
Spec: networkv1.NetworkAttachmentDefinitionSpec{
Config: `
{
"cniVersion": "0.3.1",
"name": "internalapi",
"type": "macvlan",
"master": "internalapi",
"ipam": {
"type": "whereabouts",
"range": "172.17.0.0/24",
"range_start": "172.17.0.30",
"range_end": "172.17.0.70"
}
}
`,
},
},
path: ".ipam.range",
want: "172.17.0.0/24",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)

networkAnnotation, err := GetJSONPathFromConfig(tt.nad, tt.path)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(networkAnnotation).To(HaveLen(len(tt.want)))
g.Expect(networkAnnotation).To(BeEquivalentTo(tt.want))
})
}
}

0 comments on commit d5ff7fa

Please sign in to comment.