-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add one SetFromTypedObject method to KubeObjectExt that allows to set all/any fields at once #142
Conversation
69ddcc5
to
af1d660
Compare
// SetFromTypedObject sets the value of `o` to `value`, while keeping most of the YAML formatting. | ||
// It can be seen as an in-place version of fn.NewFromTypedObject | ||
func (o *KubeObjectExt[T1]) SetFromTypedObject(value T1) error { | ||
return safeSetNestedFieldKeepFormatting(&o.KubeObject, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking instead of doing the following logic in the method safeSetNestedFieldKeepFormatting
if len(fields) == 0 {
obj2, err := fn.NewFromTypedObject(value)
if err != nil {
return err
}
*obj = *obj
Can we create the new object(obj2) in this method only, convert it to value equivalent and pass it to safeSetNestedFieldKeepFormatting
. That will keep that method consistent without any changes needed.
Does it make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pass [the new object] to
safeSetNestedFieldKeepFormatting
what would you put into the fields
parameter, when you passing the new object?
In its current form if you call safeSetNestedFieldKeepFormatting
without any fields parameter it will do nothing (this behavior is inherited from obj.SetNestedField
that it calls internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well in SetFromTypedObject
we will create the value for the passes in go struct and simply call
setNestedFieldKeepFormatting(obj, value) No fields passed i n.
Let SetNestedField take care of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately calling SetNestedField() with no fields at all is a noop: it doesn't return an error, but it doesn't do anything at all either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isnt that what we want in this case as we are not passing any fields from SetFromTypedObject?
When testing this this does not work. When applying SetStatus it works fine. func (r *fnCtx) updateIPAllocationResource(forObj *fn.KubeObject, objs fn.KubeObjects) (*fn.KubeObject, error) {
} testable using github.com/henderiw-nephio/pkg-examples -> ipam-fn |
// the caller is responsible for ensuring that `obj` is not nil` | ||
// SetFromTypedObject sets the value of `o` to `value`, while keeping most of the YAML formatting. | ||
// It can be seen as an in-place version of fn.NewFromTypedObject | ||
func (o *KubeObjectExt[T1]) SetFromTypedObject(value T1) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When testing this this does not work. When applying SetStatus it works fine.
func (r *fnCtx) updateIPAllocationResource(forObj *fn.KubeObject, objs fn.KubeObjects) (*fn.KubeObject, error) {
if forObj == nil {
return nil, fmt.Errorf("expected a for object but got nil")
}
fn.Logf("ipalloc: %v\n", forObj)
allocKOE, err := ko.NewFromKubeObject*ipamv1alpha1.IPAllocation
if err != nil {
return nil, err
}
alloc, err := allocKOE.GetGoStruct()
if err != nil {
return nil, err
}
resp, err := r.IpamClientProxy.Allocate(context.Background(), alloc, nil)
if err != nil {
return nil, err
}
alloc.Status = resp.Status
if alloc.Status.Prefix != nil {
fn.Logf("ipalloc resp prefix: %v\n", *resp.Status.Prefix)
}
if alloc.Status.Gateway != nil {
fn.Logf("ipalloc resp gateway: %v\n", *resp.Status.Gateway)
}
// set the status
//err = allocKOE.SetStatus(resp.Status)
err = allocKOE.SetFromTypedObject(resp)
return &allocKOE.KubeObject, err
}
testable using github.com/henderiw-nephio/pkg-examples -> ipam-fn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the error message that you got?
For me the following testcase is green: (however see my next comment)
func TestIpalloc(t *testing.T) {
var inputYaml string = `
apiVersion: ipam.alloc.nephio.org/v1alpha1
kind: IPAllocation
metadata:
name: internetpool1
spec:
kind: pool
selector:
matchLabels:
nephio.org/site: edge1
networkInstance: {}
prefixLength: 8
`
allocKOE, err := NewFromYaml[*ipamv1alpha1.IPAllocation]([]byte(inputYaml))
assertNoError(t, err)
alloc, err := allocKOE.GetGoStruct()
assertNoError(t, err)
alloc.Status.Gateway = "2.2.2.2"
alloc.Status.AllocatedPrefix = "3.3.3.0"
// set the status
//err = allocKOE.SetStatus(resp.Status)
err = allocKOE.SetFromTypedObject(alloc)
assertNoError(t, err)
var expectedYaml string = `apiVersion: ipam.alloc.nephio.org/v1alpha1
kind: IPAllocation
metadata:
name: internetpool1
spec:
kind: pool
networkInstance: {}
prefixLength: 8
status:
prefix: 3.3.3.0
gateway: 2.2.2.2`
actualYaml := strings.TrimSpace(allocKOE.String())
if actualYaml != expectedYaml {
t.Errorf(actualYaml)
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having said that you are using KubeObjectExt[*ipamv1alpha1.IPAllocation]
.
So far I thought that KubeObjectExt's type parameter should be a struct, as opposed to a pointer-to-struct. I came to this conclusion by looking into kubeobject_test.go (even the parts that wasn't written by me 🙂), and into the implementation of GetGoStruct():
GetGoStruct accidentally works with the pointer type parameter, but in that case we are passing a **ipamv1alpha1.IPAllocation
to As(), while I think it was designed to receive a *ipamv1alpha1.IPAllocation
.
This might also cause your different behavior between SetFromTypedObject and SetSpec. For SetSPec you pass resp.Status
that is a struct, but to SetFromTypedObject() you pass resp
that is a pointer-to-struct.
The important question here: Should we support pointer or struct type parameters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@henderiw I've managed to run your github.com/henderiw-nephio/pkg-examples -> ipam-fn code,
and for me the SetStatus and SetFromTypedObject versions ouput the exact same result (character-by character).
What is your error?
af1d660
to
e432bd5
Compare
This LGTM, but has @henderiw 's issue been figured out? |
e432bd5
to
ee7fb41
Compare
… KubeObjectExt from a go struct while keeping formatting
6b7f0a4
to
d9df376
Compare
/lgtm |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: johnbelamaric The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Inspired by this comment from @johnbelamaric : this proposal adds a setter for the whole KubeObjectExt that allows to set all/any fields at once