Kubebuilder: Add support for interface member

Created on 13 Dec 2018  路  20Comments  路  Source: kubernetes-sigs/kubebuilder

Hi,

I have a resource type that has a interface{} type.

When running go run vendor/sigs.k8s.io/controller-tools/cmd/controller-gen/main.go crdI get an error :

2018/12/13 08:35:47 Unknown supported Kind Interface

Actually, This field could contain string or int or bool but I don't want to create a IntOrStringOrBool type. Is there a workaround or is it a bug?

Thanks

kinbug lifecyclstale

Most helpful comment

@sohankunkerkar I looked at it some more and to be able to add this functionality the generator has to be altered. Here's an example that works (but is far from perfect). I need to add support to all interfaces and make sure that the copystructure package is included with dep.
https://github.com/kubernetes/gengo/compare/master...andersjanmyr:add_support_for_interface

All 20 comments

It should not error-out for interface{} type.
@sohankunkerkar can you pl. take a look at this ?

@fiftoine Could you please help me out with your test case (like an example )here? Just wanted to make sure that I'm not missing out on any information.

So happy this issue is already open - I just ran into this myself!

Are there any workarounds? @fiftoine did you get this figured out?

@tantona Could you please provide the test case that you're using here. It would help me in debugging this issue.

@sohankunkerkar Just declare a new type, like this:

type InterfaceExample struct {
    Inter interface{} `json:"inter"`
}

This will lead to an error like this:

$ make
go generate ./pkg/... ./cmd/...
F0114 14:33:10.565683   65790 main.go:82] Error: Failed executing generator: some packages had errors:
errors in package "gecgithub01.walmart.com/wce/marquis-mca/pkg/apis/marquis/v1beta1":
unable to format file "/Users/vn0wxf9/gocode/src/gecgithub01.walmart.com/wce/marquis-mca/pkg/apis/marquis/v1beta1/zz_generated.deepcopy.go" (62:39: expected ';', found '{' (and 5 more errors)).

Adding a type alias for interface{} changes the error

type Inter interface{}
type InterfaceExample struct {
    Inter Inter `json:"inter"`
}

to this

$ make
go generate ./pkg/... ./cmd/...
go fmt ./pkg/... ./cmd/...
go vet ./pkg/... ./cmd/...
# gecgithub01.walmart.com/wce/marquis-mca/pkg/apis/marquis/v1beta1
pkg/apis/marquis/v1beta1/zz_generated.deepcopy.go:69:23: in.Inter.DeepCopyInter undefined (type Inter is interface with no methods)
# gecgithub01.walmart.com/wce/marquis-mca/pkg/apis/marquis/v1beta1 [gecgithub01.walmart.com/wce/marquis-mca/pkg/apis/marquis/v1beta1.test]
pkg/apis/marquis/v1beta1/zz_generated.deepcopy.go:69:23: in.Inter.DeepCopyInter undefined (type Inter is interface with no methods)
make: *** [vet] Error 2

I think something like Mitchell Hashimoto's copystructure could be used to solve this.
https://godoc.org/github.com/mitchellh/copystructure

@andersjanmyr Thanks for the detailed analysis. I understood what's the problem here. Let me go through it and will get back to you soon.

@sohankunkerkar I looked at it some more and to be able to add this functionality the generator has to be altered. Here's an example that works (but is far from perfect). I need to add support to all interfaces and make sure that the copystructure package is included with dep.
https://github.com/kubernetes/gengo/compare/master...andersjanmyr:add_support_for_interface

After the above change is applied, the following patch needs to be applied to sigs.k8s.io/controller-tools to generate a property with type: object in the CRD.

--- a/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/crd.go
+++ b/vendor/sigs.k8s.io/controller-tools/pkg/internal/codegen/parse/crd.go
@@ -198,6 +198,8 @@ func (b *APIs) typeToJSONSchemaProps(t *types.Type, found sets.String, comments
                v, s = b.typeToJSONSchemaProps(t.Elem, found, comments, false)
        case types.Alias:
                v, s = b.typeToJSONSchemaProps(t.Underlying, found, comments, false)
+       case types.Interface:
+               v, s = b.parseObjectValidation(t, found, comments, isRoot)

@andersjanmyr That's awesome. I was planning to handle this condition in the controller-tools itself.
https://github.com/kubernetes-sigs/controller-tools/compare/master...sohankunkerkar:interface?expand=1
I did not change anything in gengo package

@sohankunkerkar How does the generated copy code look? The zz_generated.deepcopy.go must make a deep copy using reflection for interfaces. I don't think you can get that to work without using reflection.

Stumbled upon this today as well. Reading the thread of comments it seems two issues are actually entangled here:

  • one is about generation of the CRD
  • one is about generation of the deepcopy code

My use-case is a bit similar to the one described above, although in my case, the structure member is a map[string]interface{}. I was able to circumvent the deepcopy issue by creating the DeepCopy and DeepCopyInto functions manually but I can't get past the CRD.

Here is the code that handles the copy (maybe helpful to other people):

// +k8s:deepcopy-gen=false
type ExtraFields map[string]interface{}

func (in *ExtraFields) DeepCopyInto(out *ExtraFields) {
    if in == nil {
        *out = nil
    } else {
        *out = runtime.DeepCopyJSON(*in)
    }
}

func (in *ExtraFields) DeepCopy() *ExtraFields {
    if in == nil {
        return nil
    }
    out := new(ExtraFields)
    in.DeepCopyInto(out)
    return out
}

@j-vizcaino Could you provide your feedback over here?
https://github.com/kubernetes-sigs/controller-tools/pull/126

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

this should have been fixed in the latest release of CT, IIRC

I'm using version 2.0.0-beta.0 of Kubebuilder and still seeing this problem. I've verified that I'm using the latest version of CT, 0.2.0-beta.4. My interface looks like this:

type DeploymentTargetSpec struct {
    DeploymentPatchSet []interface{} `json:"deploymentPatchSet"`
}

Seeing the error message:

github.com/.../api/v1beta1:-: name requested for invalid type interface{}
github.com/.../api/v1beta1:-: invalid slice element type interface{}

Is there something I'm still doing wrong? It's also worth noting that this happens without the slice as well.

no fixed in master. @DirectXMan12
go run vendor/sigs.k8s.io/controller-tools/cmd/controller-gen/main.go crd paths=./pkg/apis/aiops/... output:crd:dir=/tmp/crds
error:
map values must be a named type, not *ast.InterfaceType

same problem:
https://github.com/kubernetes-sigs/controller-tools/issues/294

I've replied on the equivalent controller-tools issue. Please direct all comments there.

I've locked this in the hopes that we can keep discussion in one place, not to discourage filing of issues. In general, generation issues should be discussed in the controller-tools repo.

Was this page helpful?
0 / 5 - 0 ratings