From 76386373577c70a3a302c6aaa48fd301ffb173b2 Mon Sep 17 00:00:00 2001 From: haozi007 Date: Mon, 22 Nov 2021 06:27:29 +0000 Subject: [PATCH 2/3] improve coverage of ut Signed-off-by: haozi007 --- tests/CMakeLists.txt | 11 + tests/api_llt.cpp | 382 +++++++++++++++++++++++++++++- tests/confs/default-invalid.conf | 13 + tests/confs/default.json | 13 + tests/confs/test-bad.conflist | 12 + tests/confs/test-invalid.conflist | 12 + tests/confs/test.conflist | 12 + tests/utils/bridge | 16 ++ tests/utils/bridge-bad | 8 + tests/utils/constants.h | 19 ++ tests/utils/host-local | 8 + tests/utils/loopback | 8 + tests/utils/portmap | 8 + 13 files changed, 517 insertions(+), 5 deletions(-) create mode 100644 tests/confs/default-invalid.conf create mode 100644 tests/confs/default.json create mode 100644 tests/confs/test-bad.conflist create mode 100644 tests/confs/test-invalid.conflist create mode 100644 tests/confs/test.conflist create mode 100755 tests/utils/bridge create mode 100755 tests/utils/bridge-bad create mode 100755 tests/utils/host-local create mode 100755 tests/utils/loopback create mode 100755 tests/utils/portmap diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e2571a0..b1f5c35 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,6 +19,17 @@ include_directories( add_subdirectory(utils) +file(COPY utils/loopback DESTINATION utils/) +file(COPY utils/bridge DESTINATION utils/) +file(COPY utils/portmap DESTINATION utils/) +file(COPY utils/host-local DESTINATION utils/) +file(COPY utils/bridge-bad DESTINATION utils/) +file(COPY confs/default-invalid.conf DESTINATION confs/) +file(COPY confs/default.json DESTINATION confs/) +file(COPY confs/test-bad.conflist DESTINATION confs/) +file(COPY confs/test-invalid.conflist DESTINATION confs/) +file(COPY confs/test.conflist DESTINATION confs/) + macro(_DEFINE_NEW_TEST) add_executable(${ARGV0} ${TESTS_UTILS_SRCS} diff --git a/tests/api_llt.cpp b/tests/api_llt.cpp index d21ec01..186c76b 100644 --- a/tests/api_llt.cpp +++ b/tests/api_llt.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "api.h" #include "version.h" @@ -130,9 +131,9 @@ TEST(api_testcases, cni_conflist_from_conf) struct cni_network_list_conf *new_list = NULL; char *err = NULL; struct cni_network_conf test = { - .name = "default", - .type = "bridge", - .bytes = COMMON_CONF, + .name = (char *)"default", + .type = (char *)"bridge", + .bytes = (char *)COMMON_CONF, }; ret = cni_conflist_from_conf(&test, &new_list, &err); @@ -150,6 +151,15 @@ TEST(api_testcases, cni_conflist_from_conf) TEST(api_testcases, get_version_info) { + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + + pwd = strcat(pwd_buf, "/utils"); + ASSERT_NE(pwd, nullptr); + const std::string CNI_PLUGIN_PATH = "/opt/cni/bin/"; char *err = nullptr; struct plugin_info *pinfo = nullptr; @@ -162,14 +172,24 @@ TEST(api_testcases, get_version_info) if (ret != 0) { if (strstr(err, "No such file or directory") != nullptr) { std::cout << "Skip: cni_get_version_info api cause by no bridge plugin found" << std::endl; - return; + ret = 0; } std::cout << "Get version failed:" << err << std::endl; } ASSERT_EQ(ret, 0); + free(err); + err = nullptr; + + free(paths[0]); + paths[0] = strdup(pwd_buf); + ret = cni_get_version_info(bridge_name.c_str(), paths, &pinfo, &err); + if (ret != 0) { + std::cout << "Get version failed:" << err << std::endl; + } + ASSERT_EQ(ret, 0); /* check plugin info */ - EXPECT_STREQ("0.4.0", pinfo->cniversion); + EXPECT_STREQ("0.3.1", pinfo->cniversion); ASSERT_LE(0, pinfo->supported_versions_len); for (i = 0; i < pinfo->supported_versions_len; i++) { if (strcmp(pinfo->supported_versions[i], CURRENT_VERSION) == 0) { @@ -183,3 +203,355 @@ TEST(api_testcases, get_version_info) paths[0] = nullptr; } +TEST(api_testcases, cni_log_ops) +{ + int ret = 0; + + ret = cni_log_init("xxx", "/tmp/cni.log", "debug"); + ASSERT_NE(ret, 0); + ret = cni_log_init("file", "xxx", "debug"); + ASSERT_NE(ret, 0); + ret = cni_log_init("file", "/tmp/cni.log", "xxx"); + ASSERT_NE(ret, 0); + + ret = cni_log_init("stdout", nullptr, "debug"); + ASSERT_EQ(ret, 0); + + cni_set_log_prefix("xxx"); + + cni_free_log_prefix(); +} + +TEST(api_testcases, cni_add_network_list) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *paths[] = {pwd_buf, nullptr}; + pid_t cpid = getpid(); + char netns[PATH_MAX] = {0x0}; + char *err = NULL; + struct runtime_conf rc = { + .container_id = (char *)"abcd", + .netns = netns, + .ifname = (char *)"eth0", + .p_mapping_len = 1, + }; + struct result *pret = nullptr; + + rc.p_mapping = (struct cni_port_mapping **)calloc(1, sizeof(struct cni_port_mapping *)); + ASSERT_NE(rc.p_mapping, nullptr); + rc.p_mapping[0] = (struct cni_port_mapping *)calloc(1, sizeof(struct cni_port_mapping)); + ASSERT_NE(rc.p_mapping[0], nullptr); + rc.p_mapping[0]->container_port = 80; + rc.p_mapping[0]->host_port = 8080; + + (void)sprintf(netns, "/proc/%d/ns/net", cpid); + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + + pwd = strcat(pwd_buf, "/utils"); + ASSERT_NE(pwd, nullptr); + + std::cout << "cni bin path: " << pwd_buf << std::endl; + + ret = cni_add_network_list(COMMON_CONF_LIST, &rc, paths, &pret, &err); + ASSERT_EQ(ret, 0); + ASSERT_EQ(err, nullptr); + free_result(pret); + pret = nullptr; + + std::cout << "cni bin path with cap: " << pwd_buf << std::endl; + ret = cni_add_network_list(CONF_LIST_WITH_PORTMAP, &rc, paths, &pret, &err); + ASSERT_EQ(ret, 0); + ASSERT_EQ(err, nullptr); + free_result(pret); + pret = nullptr; + + std::cout << "invlaid config list" << std::endl; + ret = cni_add_network_list(INVALID_COMMON_CONF_LIST, &rc, paths, &pret, &err); + ASSERT_NE(ret, 0); + free_result(pret); + pret = nullptr; + free(err); + err = nullptr; + + std::cout << "bad config list" << std::endl; + ret = cni_add_network_list(BAD_COMMON_CONF_LIST, &rc, paths, &pret, &err); + ASSERT_NE(ret, 0); + free_result(pret); + pret = nullptr; + + free(err); +} + +TEST(api_testcases, cni_add_network) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *paths[] = {pwd_buf, nullptr}; + pid_t cpid = getpid(); + char netns[PATH_MAX] = {0x0}; + char *err = NULL; + struct runtime_conf rc = { + .container_id = (char *)"abcd", + .netns = netns, + .ifname = (char *)"eth0", + .p_mapping_len = 1, + }; + struct result *pret = nullptr; + + rc.p_mapping = (struct cni_port_mapping **)calloc(1, sizeof(struct cni_port_mapping *)); + ASSERT_NE(rc.p_mapping, nullptr); + rc.p_mapping[0] = (struct cni_port_mapping *)calloc(1, sizeof(struct cni_port_mapping)); + ASSERT_NE(rc.p_mapping[0], nullptr); + rc.p_mapping[0]->container_port = 80; + rc.p_mapping[0]->host_port = 8080; + + (void)sprintf(netns, "/proc/%d/ns/net", cpid); + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + + pwd = strcat(pwd_buf, "/utils"); + ASSERT_NE(pwd, nullptr); + + std::cout << "cni bin path: " << pwd_buf << std::endl; + + ret = cni_add_network(COMMON_CONF, &rc, paths, &pret, &err); + ASSERT_EQ(ret, 0); + free_result(pret); + pret = nullptr; + + ret = cni_add_network(INVALID_COMMON_CONF, &rc, paths, &pret, &err); + ASSERT_NE(ret, 0); + free_result(pret); + pret = nullptr; + + free(err); +} + +TEST(api_testcases, cni_delete_network_list) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *paths[] = {pwd_buf, nullptr}; + pid_t cpid = getpid(); + char netns[PATH_MAX] = {0x0}; + char *err = NULL; + struct runtime_conf rc = { + .container_id = (char *)"abcd", + .netns = netns, + .ifname = (char *)"eth0", + }; + + (void)sprintf(netns, "/proc/%d/ns/net", cpid); + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + + pwd = strcat(pwd_buf, "/utils"); + ASSERT_NE(pwd, nullptr); + + std::cout << "cni bin path: " << pwd_buf << std::endl; + + ret = cni_del_network_list(COMMON_CONF_LIST, &rc, paths, &err); + ASSERT_EQ(ret, 0); + + std::cout << "delete with invlaid config list" << std::endl; + ret = cni_del_network_list(INVALID_COMMON_CONF_LIST, &rc, paths, &err); + ASSERT_NE(ret, 0); + free(err); + err = nullptr; + + std::cout << "delete with bad config list" << std::endl; + ret = cni_del_network_list(BAD_COMMON_CONF_LIST, &rc, paths, &err); + ASSERT_NE(ret, 0); + + free(err); +} + +TEST(api_testcases, cni_delete_network) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *paths[] = {pwd_buf, nullptr}; + pid_t cpid = getpid(); + char netns[PATH_MAX] = {0x0}; + char *err = NULL; + struct runtime_conf rc = { + .container_id = (char *)"abcd", + .netns = netns, + .ifname = (char *)"eth0", + }; + + (void)sprintf(netns, "/proc/%d/ns/net", cpid); + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + + pwd = strcat(pwd_buf, "/utils"); + ASSERT_NE(pwd, nullptr); + + std::cout << "cni bin path: " << pwd_buf << std::endl; + + ret = cni_del_network(COMMON_CONF, &rc, paths, &err); + ASSERT_EQ(ret, 0); + + ret = cni_del_network(INVALID_COMMON_CONF, &rc, paths, &err); + ASSERT_NE(ret, 0); + + free(err); +} + +TEST(api_testcases, cni_conf_files) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *paths[] = {pwd_buf, nullptr}; + char *err = NULL; + const char *exts[] = {"json", "conf", "conflist"}; + char **result = nullptr; + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + + pwd = strcat(pwd_buf, "/confs"); + ASSERT_NE(pwd, nullptr); + + std::cout << "cni conf path: " << pwd_buf << std::endl; + + ret = cni_conf_files(pwd_buf, exts, 3, &result, &err); + ASSERT_EQ(ret, 0); + free(err); + err = nullptr; + + ret = cni_conf_files("xxxx", exts, 3, &result, &err); + ASSERT_EQ(ret, 0); + free(err); + err = nullptr; + + ret = cni_conf_files(pwd_buf, exts, 3, &result, nullptr); + ASSERT_NE(ret, 0); + + free(err); +} + +TEST(api_testcases, cni_conf_from_file) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *err = NULL; + struct cni_network_conf *config = nullptr; + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + pwd = strcat(pwd_buf, "/confs/default-invalid.conf"); + ASSERT_NE(pwd, nullptr); + std::cout << "cni conf path: " << pwd_buf << std::endl; + ret = cni_conf_from_file(pwd_buf, &config, &err); + ASSERT_EQ(ret, 0); + ASSERT_NE(config, nullptr); + free(err); + err = nullptr; + free_cni_network_conf(config); + config = nullptr; + memset(pwd_buf, 0, PATH_MAX); + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + pwd = strcat(pwd_buf, "/confs/default.json"); + ASSERT_NE(pwd, nullptr); + std::cout << "cni conf path: " << pwd_buf << std::endl; + ret = cni_conf_from_file(pwd_buf, &config, &err); + ASSERT_EQ(ret, 0); + ASSERT_NE(config, nullptr); + free(err); + err = nullptr; + free_cni_network_conf(config); + config = nullptr; + memset(pwd_buf, 0, PATH_MAX); + + ret = cni_conf_from_file("/tmp/xxx/xxx.json", &config, &err); + ASSERT_NE(ret, 0); + ASSERT_EQ(config, nullptr); + free(err); + err = nullptr; +} + + +TEST(api_testcases, cni_conflist_from_file) +{ + int ret = 0; + char pwd_buf[PATH_MAX] = {0X0}; + char *pwd = nullptr; + char *err = NULL; + struct cni_network_list_conf *list = nullptr; + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + pwd = strcat(pwd_buf, "/confs/test-invalid.conflist"); + ASSERT_NE(pwd, nullptr); + std::cout << "cni conflist path: " << pwd_buf << std::endl; + ret = cni_conflist_from_file(pwd_buf, &list, &err); + ASSERT_EQ(ret, 0); + ASSERT_NE(list, nullptr); + free(err); + err = nullptr; + free_cni_network_list_conf(list); + list = nullptr; + memset(pwd_buf, 0, PATH_MAX); + + pwd = getcwd(pwd_buf, PATH_MAX); + ASSERT_NE(pwd, nullptr); + pwd = strcat(pwd_buf, "/confs/test.conflist"); + ASSERT_NE(pwd, nullptr); + std::cout << "cni conflist path: " << pwd_buf << std::endl; + ret = cni_conflist_from_file(pwd_buf, &list, &err); + ASSERT_EQ(ret, 0); + ASSERT_NE(list, nullptr); + free(err); + err = nullptr; + free_cni_network_list_conf(list); + list = nullptr; + memset(pwd_buf, 0, PATH_MAX); + + ret = cni_conflist_from_file("/tmp/xxx/xxx.json", &list, &err); + ASSERT_NE(ret, 0); + ASSERT_EQ(list, nullptr); + free(err); + err = nullptr; +} + +TEST(api_testcases, free_cni_port_mapping) +{ + int ret = 0; + struct cni_port_mapping *cpm = (struct cni_port_mapping *)malloc(sizeof(struct cni_port_mapping)); + + cpm->container_port = 80; + cpm->host_port = 8080; + cpm->protocol = strdup("tcp"); + cpm->host_ip = nullptr; + + free_cni_port_mapping(cpm); +} + +TEST(api_testcases, free_runtime_conf) +{ + int ret = 0; + struct runtime_conf *rc = (struct runtime_conf *)calloc(sizeof(struct runtime_conf), 1); + + rc->ifname = strdup("eth0"); + rc->p_mapping_len = 2; + rc->p_mapping = (struct cni_port_mapping **)calloc(sizeof(struct cni_port_mapping *), 2); + rc->p_mapping[0] = (struct cni_port_mapping *)calloc(sizeof(struct cni_port_mapping), 1); + rc->p_mapping[1] = (struct cni_port_mapping *)calloc(sizeof(struct cni_port_mapping), 1); + + free_runtime_conf(rc); +} \ No newline at end of file diff --git a/tests/confs/default-invalid.conf b/tests/confs/default-invalid.conf new file mode 100644 index 0000000..75596cb --- /dev/null +++ b/tests/confs/default-invalid.conf @@ -0,0 +1,13 @@ +{ + "cniVersion": "0.3.1", + "name": "invalid-conf", + "type": "xxxx", + "bridge": "cni0", + "isGateway": "true", + "ipam": { + "type": "host-local", + "subnet": "10.1.0.0/16", + "gateway": "10.1.0.1" + }, + "dns": {"nameservers": ["10.1.0.1"]} +} \ No newline at end of file diff --git a/tests/confs/default.json b/tests/confs/default.json new file mode 100644 index 0000000..5ff3def --- /dev/null +++ b/tests/confs/default.json @@ -0,0 +1,13 @@ +{ + "cniVersion": "0.3.1", + "name": "default", + "type": "bridge", + "bridge": "cni0", + "isGateway": "true", + "ipam": { + "type": "host-local", + "subnet": "10.1.0.0/16", + "gateway": "10.1.0.1" + }, + "dns": {"nameservers": ["10.1.0.1"]} +} \ No newline at end of file diff --git a/tests/confs/test-bad.conflist b/tests/confs/test-bad.conflist new file mode 100644 index 0000000..bc6cad7 --- /dev/null +++ b/tests/confs/test-bad.conflist @@ -0,0 +1,12 @@ +{ + "cniVersion": "0.3.1", + "name": "test", + "plugins": [ + { + "cniVersion": "0.3.1", "name": "test", "type": "bridge-bad" + }, + { + "name": "exist", "type": "bridge-bad", "dns": {"nameservers": ["10.1.0.1"]} + } + ] +} \ No newline at end of file diff --git a/tests/confs/test-invalid.conflist b/tests/confs/test-invalid.conflist new file mode 100644 index 0000000..544fddd --- /dev/null +++ b/tests/confs/test-invalid.conflist @@ -0,0 +1,12 @@ +{ + "cniVersion": "0.3.1", + "name": "test", + "plugins": [ + { + "cniVersion": "0.3.1", "name": "test", "type": "xxxx" + }, + { + "name": "exist", "type": "bridge", "dns": {"nameservers": ["10.1.0.1"]} + } + ] +} \ No newline at end of file diff --git a/tests/confs/test.conflist b/tests/confs/test.conflist new file mode 100644 index 0000000..7171dcc --- /dev/null +++ b/tests/confs/test.conflist @@ -0,0 +1,12 @@ +{ + "cniVersion": "0.3.1", + "name": "test", + "plugins": [ + { + "cniVersion": "0.3.1", "name": "test", "type": "bridge" + }, + { + "name": "exist", "type": "bridge", "dns": {"nameservers": ["10.1.0.1"]} + } + ] +} \ No newline at end of file diff --git a/tests/utils/bridge b/tests/utils/bridge new file mode 100755 index 0000000..815ba74 --- /dev/null +++ b/tests/utils/bridge @@ -0,0 +1,16 @@ +#!/bin/bash + +echo "{ + \"cniVersion\": \"0.3.1\", + \"supportedVersions\": [ \"0.1.0\", \"0.2.0\", \"0.3.0\", \"0.3.1\" ], + \"routes\": [ {\"dst\": \"192.168.1.0/24\", \"gw\": \"192.168.1.1\"} ], + \"interfaces\": [ + {\"name\": \"eth0\", \"mac\": \"ab:ab:ab:ab:ab:ab\", \"sandbox\": \"/proc/xx/ns/net\"} + ], + \"ips\": [ + {\"address\": \"192.168.1.2/24\", \"gateway\": \"192.168.1.1\", \"interface\": 1} + ], + \"dns\":{\"nameservers\": [\"test.com\"], \"domain\": \"test.com\", \"search\": [\"test\"], \"options\": [\"test\"]} +}" + +exit 0 \ No newline at end of file diff --git a/tests/utils/bridge-bad b/tests/utils/bridge-bad new file mode 100755 index 0000000..02a90d4 --- /dev/null +++ b/tests/utils/bridge-bad @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "{ + \"cniVersion\": \"0.3.1\", + \"dns\": {} +}" + +exit 1 \ No newline at end of file diff --git a/tests/utils/constants.h b/tests/utils/constants.h index 1f06bfc..afeaff8 100644 --- a/tests/utils/constants.h +++ b/tests/utils/constants.h @@ -25,11 +25,30 @@ extern "C" { \"plugins\":[{\"cniVersion\":\"0.3.0\", \"name\":\"default\",\"type\":\"bridge\"}, \ {\"name\": \"exist\",\"type\": \"bridge\", \"dns\": {\"nameservers\": [\"10.1.0.1\"]}}]}" +#define CONF_LIST_WITH_PORTMAP "{\"cniVersion\":\"0.3.0\",\"name\":\"default\", \ + \"plugins\":[{\"cniVersion\":\"0.3.0\", \"name\":\"default\",\"type\":\"bridge\"}, \ + {\"type\": \"portmap\", \"capabilities\": { \"portMappings\": true } }]}" + #define COMMON_CONF "{\"cniVersion\":\"0.3.0\",\"name\":\"default\", \ \"type\": \"bridge\", \"bridge\": \"cni0\", \"isGateway\": \"true\", \ \"ipam\": {\"type\": \"host-local\", \"subnet\": \"10.1.0.0/16\", \"gateway\": \"10.1.0.1\"},\ \"dns\": {\"nameservers\": [\"10.1.0.1\"]}}" + +#define INVALID_COMMON_CONF_LIST "{\"cniVersion\":\"0.3.0\",\"name\":\"default\", \ + \"plugins\":[{\"cniVersion\":\"0.3.0\", \"name\":\"default\",\"type\":\"bridge\"}, \ + {\"name\": \"exist\",\"type\": \"xxxx\", \"dns\": {\"nameservers\": [\"10.1.0.1\"]}}]}" + +#define INVALID_COMMON_CONF "{\"cniVersion\":\"0.3.0\",\"name\":\"default\", \ + \"type\": \"xxxx\", \"bridge\": \"cni0\", \"isGateway\": \"true\", \ + \"ipam\": {\"type\": \"host-local\", \"subnet\": \"10.1.0.0/16\", \"gateway\": \"10.1.0.1\"},\ + \"dns\": {\"nameservers\": [\"10.1.0.1\"]}}" + + +#define BAD_COMMON_CONF_LIST "{\"cniVersion\":\"0.3.0\",\"name\":\"default\", \ + \"plugins\":[{\"cniVersion\":\"0.3.0\", \"name\":\"default\",\"type\":\"bridge-bad\"}, \ + {\"name\": \"exist\",\"type\": \"bridge\", \"dns\": {\"nameservers\": [\"10.1.0.1\"]}}]}" + #ifdef __cplusplus } #endif diff --git a/tests/utils/host-local b/tests/utils/host-local new file mode 100755 index 0000000..1dd4ae5 --- /dev/null +++ b/tests/utils/host-local @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "{ + \"cniVersion\": \"0.3.1\", + \"dns\": {} +}" + +exit 0 \ No newline at end of file diff --git a/tests/utils/loopback b/tests/utils/loopback new file mode 100755 index 0000000..1dd4ae5 --- /dev/null +++ b/tests/utils/loopback @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "{ + \"cniVersion\": \"0.3.1\", + \"dns\": {} +}" + +exit 0 \ No newline at end of file diff --git a/tests/utils/portmap b/tests/utils/portmap new file mode 100755 index 0000000..1dd4ae5 --- /dev/null +++ b/tests/utils/portmap @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "{ + \"cniVersion\": \"0.3.1\", + \"dns\": {} +}" + +exit 0 \ No newline at end of file -- 2.20.1