简体   繁体   English

为休息映射器 k8s 创建假数据

[英]Create fake data for rest mapper k8s

I running the following code which works when I'm providing a kubeconfig I was able to get the value of 'gr`我运行以下代码,该代码在提供 kubeconfig 时有效,我能够获得“gr”的值

func (o *ApplyOptions) RestMapper() (meta.RESTMapper, error) {
    gr, err := restmapper.GetAPIGroupResources(o.discoveryClient)
    if err != nil {
        return nil, err
    }
    mapper := restmapper.NewDiscoveryRESTMapper(gr)
    return mapper, nil
}

I 've initiated it with the following code我用下面的代码启动了它

var kubeconfig *string

kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")

flag.Parse()

// use the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
    panic(err.Error())
}

dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
    panic(err.Error())
}
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil {
    panic(err.Error())
}

applyOptions := apply.NewApplyOptions(dynamicClient, discoveryClient)
if err := applyOptions.Apply(context.Background(), []byte(applyStr)); err != nil {
    log.Fatalf("apply error: %v", err)
}

Now I use it for unit test and I got the gr empty (from restmapper.GetAPIGroupResources(o.discoveryClient) ) above when debug it, , how can I add some fake to make it works also from the test ?现在我将它用于单元测试,并且在调试它时我得到了上面的gr空(来自restmapper.GetAPIGroupResources(o.discoveryClient) ),我如何添加一些假以使其在测试中也能正常工作?

var _ = DescribeTable(“test”, func(applyOptions *ApplyOptions, filename string, isExpectedErr bool, expectedErrMsg string) {


    applyOptions = ApplyOptions{
        discoveryClient: clientset.Discovery() ,
        //discoveryClient: &k8sfake.Clientset,
        dynamicClient:   dynamicfake.NewSimpleDynamicClient(runtime.NewScheme()),

    }

   // Here I need to initiate some fake data
    restmapper, err := applyOptions.RestMapper()
    if err != nil {
        Fail(err.Error())
    }

The error which I got is "k8s.io/apimachinery/pkg/api/ meta.NoKindMatchError "我得到的错误是“ k8s.io/apimachinery/pkg/api/meta.NoKindMatchError

update更新

To make it more clear I just trying to create a unit test for this function with kind: deployment and I got the error above.为了更清楚,我只是尝试使用kind: deployment为这个函数创建一个单元测试,我得到了上面的错误。

https://github.com/pytimer/k8sutil/blob/main/apply/apply.go#L119 https://github.com/pytimer/k8sutil/blob/main/apply/apply.go#L119

One possible approach is to abstract the restmapper away, this will make ApplyOptions to rely on abstractions, thus you can mock it.一种可能的方法是将restmapper抽象出来,这将使ApplyOptions依赖于抽象,因此您可以模拟它。 Assuming you are unit testing.假设你是单元测试。

We can call it RESTMapperDiscovery this type will encapsulate the restmapper capabilities used by ApplyOptions .我们可以把它叫做RESTMapperDiscovery这个类型将封装restmapper通过使用功能ApplyOptions It is basically a wrapper.它基本上是一个包装器。

type RESTMapperDiscovery struct {}
func (RESTMapperDiscovery) FromGroupResources(cl discovery.DiscoveryInterface) (meta.RESTMapper, error)

FromGroupResources will concretely implement the code currently part of func (o *ApplyOptions) RestMapper() . FromGroupResources将具体实现func (o *ApplyOptions) RestMapper()当前部分的代码。

To achieve polymorphism we just need an interface.为了实现多态,我们只需要一个接口。

type DiscoveryRESTMapper interface {
    FromGroupResources(cl discovery.DiscoveryInterface) (meta.RESTMapper, error)
}

At this stage ApplyOptions will also depend on DiscoveryRESTMapper .在这个阶段ApplyOptions也将依赖DiscoveryRESTMapper

type ApplyOptions struct {
    //... other fields
    restMapper DiscoveryRESTMapper
}
func (o *ApplyOptions) RestMapper() (meta.RESTMapper, error) {
    return o.restMapper.FromGroupResources(o.discoveryClient)
}

When testing, you can use a type which fulfils that interface and will return some fake data.测试时,您可以使用满足该接口的类型并返回一些假数据。 meta.RESTMapper is an interface as well, thereof your fake data has to implement. meta.RESTMapper也是一个接口,你的假数据必须实现。

type mockRESTMapper struct {}
func (mockRESTMapper) FromGroupResources(cl discovery.DiscoveryInterface) (meta.RESTMapper, error) {
    // return the fake meta.RESTMapper
}

applyOptions = &ApplyOptions{
    discoveryClient: clientset.Discovery() ,
    dynamicClient:   dynamicfake.NewSimpleDynamicClient(runtime.NewScheme()),
    restMapper: mockRESTMapper{},

}

// here you have the fake data
restmapper, err := applyOptions.RestMapper()
if err != nil {
    Fail(err.Error())
}

This approach relies on composition and interfaces to decouple external dependencies.这种方法依赖于组合和接口来解耦外部依赖。 k8s apis as restmapper seems to rely on the same mechanism, thus you could also mock all that from the currently dependencies of ApplyOptions .作为restmapper k8s apis 似乎依赖于相同的机制,因此您也可以从ApplyOptions的当前依赖项中模拟所有这些。 The trade-off here is your solution being tightly coupled with k8s api, this could result in break changes with restmapper versions and/or maintenance burden.这里的权衡是您的解决方案与 k8s api 紧密耦合,这可能会导致restmapper版本和/或维护负担的中断更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM