Template code for calling identical C++ APIs from different namespaces

51 Views Asked by At

Kubernetes has two very similar versions for their CRI API (v1 and v1alpha), defined here:

https://github.com/kubernetes/cri-api/blob/release-1.25/pkg/apis/runtime/v1/api.proto
https://github.com/kubernetes/cri-api/blob/release-1.25/pkg/apis/runtime/v1alpha/api.proto

These get converted using protoc to C++ headers which clients use to make remote API calls. Some Kubernetes clusters support only v1alpha, some only v1 and some both.

The client code looks like this:

auto stub = runtime::v1::RuntimeService::NewStub(unixSockPath);
runtime::v1::ListContainersRequest req;
runtime::v1::ListContainersResponse resp;
stub->ListContainers(req, &res);

or like this, depending on which version is supported by the server:

auto stub = runtime::v1alpha::RuntimeService::NewStub(unixSockPath);
runtime::v1alpha::ListContainersRequest req;
runtime::v1alpha::ListContainersResponse resp;
stub->ListContainers(req, &res);

(only the type names have changed.)

So clients have to try with v1 first and fallback to v1alpha if v1 is not supported.

Is there a way to write a template function that issues the above requests and uses the namespace (runtime::v1, runtime::v1alpha) as a template parameter ? This would enable writing code like:

std::list<std::string> listContainers() {
    try {
        if (g_useV1)
            return __listContainers<runtime::v1>();
    } catch (const not_supported &ex) {
        g_useV1 = false;
    }
    
    return __listContainers<runtime::v1alpha>();
}

Or is passing all the used typenames (RuntimeService::NewStub, ListContainerRequest etc) as template parameters the only option ?

0

There are 0 best solutions below