未验证 提交 1739712f 编写于 作者: Y Yang Zhao 提交者: GitHub

enh: support url in commandline taos shell (#13792)

* enh: support url in commandline taos shell

* fix: normal host logic

* enh: add default -R if env var set

* fix: refine taos shell cloud service

* fix: improve user friendly
上级 28ca8346
...@@ -48,13 +48,11 @@ typedef struct SShellArguments { ...@@ -48,13 +48,11 @@ typedef struct SShellArguments {
char* database; char* database;
char* timezone; char* timezone;
bool restful; bool restful;
char* token;
#ifdef WINDOWS #ifdef WINDOWS
SOCKET socket; SOCKET socket;
#else #else
int socket; int socket;
#endif #endif
TAOS* con; TAOS* con;
bool is_raw_time; bool is_raw_time;
bool is_use_passwd; bool is_use_passwd;
...@@ -70,6 +68,8 @@ typedef struct SShellArguments { ...@@ -70,6 +68,8 @@ typedef struct SShellArguments {
int pktNum; int pktNum;
char* pktType; char* pktType;
char* netTestRole; char* netTestRole;
char* cloudDsn;
bool cloud;
} SShellArguments; } SShellArguments;
typedef enum WS_ACTION_TYPE_S { WS_CONN, WS_QUERY, WS_FETCH, WS_FETCH_BLOCK } WS_ACTION_TYPE; typedef enum WS_ACTION_TYPE_S { WS_CONN, WS_QUERY, WS_FETCH, WS_FETCH_BLOCK } WS_ACTION_TYPE;
......
...@@ -62,8 +62,8 @@ void printHelp() { ...@@ -62,8 +62,8 @@ void printHelp() {
printf("%s%s%s\n", indent, indent, "Number of threads when using multi-thread to import data."); printf("%s%s%s\n", indent, indent, "Number of threads when using multi-thread to import data.");
printf("%s%s\n", indent, "-R"); printf("%s%s\n", indent, "-R");
printf("%s%s%s\n", indent, indent, "Connect and interact with TDengine use restful."); printf("%s%s%s\n", indent, indent, "Connect and interact with TDengine use restful.");
printf("%s%s\n", indent, "-t"); printf("%s%s\n", indent, "-E");
printf("%s%s%s\n", indent, indent, "The token to use when connecting TDengine's cloud services."); printf("%s%s%s\n", indent, indent, "The DSN to use when connecting TDengine's cloud services.");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -76,20 +76,13 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -76,20 +76,13 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
// for host // for host
if (strcmp(argv[i], "-h") == 0) { if (strcmp(argv[i], "-h") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
char* arg = argv[++i]; arguments->cloud = false;
char* tmp = strstr(arg, ":"); arguments->host = argv[++i];
if (tmp == NULL) { } else {
arguments->host = arg; fprintf(stderr, "option -h requires an argument\n");
} else if ((tmp + 1) != NULL) { exit(EXIT_FAILURE);
arguments->port = atoi(tmp + 1); }
tmp[0] = '\0';
arguments->host = arg;
}
} else {
fprintf(stderr, "option -h requires an argument\n");
exit(EXIT_FAILURE);
}
} }
// for password // for password
else if ((strncmp(argv[i], "-p", 2) == 0) else if ((strncmp(argv[i], "-p", 2) == 0)
...@@ -116,6 +109,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -116,6 +109,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
// for management port // for management port
else if (strcmp(argv[i], "-P") == 0) { else if (strcmp(argv[i], "-P") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
arguments->cloud = false;
arguments->port = atoi(argv[++i]); arguments->port = atoi(argv[++i]);
} else { } else {
fprintf(stderr, "option -P requires an argument\n"); fprintf(stderr, "option -P requires an argument\n");
...@@ -132,6 +126,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -132,6 +126,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
} else if (strcmp(argv[i], "-c") == 0) { } else if (strcmp(argv[i], "-c") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
arguments->cloud = false;
if (strlen(argv[++i]) >= TSDB_FILENAME_LEN) { if (strlen(argv[++i]) >= TSDB_FILENAME_LEN) {
fprintf(stderr, "config file path: %s overflow max len %d\n", argv[i], TSDB_FILENAME_LEN - 1); fprintf(stderr, "config file path: %s overflow max len %d\n", argv[i], TSDB_FILENAME_LEN - 1);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -203,14 +198,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -203,14 +198,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
else if (strcmp(argv[i], "-R") == 0) { else if (strcmp(argv[i], "-R") == 0) {
arguments->cloud = false;
arguments->restful = true; arguments->restful = true;
} }
else if (strcmp(argv[i], "-t") == 0) { else if (strcmp(argv[i], "-E") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
arguments->token = argv[++i]; arguments->cloudDsn = argv[++i];
} else { } else {
fprintf(stderr, "options -t requires an argument\n"); fprintf(stderr, "options -E requires an argument\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -225,6 +221,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -225,6 +221,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (args.cloudDsn == NULL) {
if (args.cloud) {
args.cloudDsn = getenv("TDENGINE_CLOUD_DSN");
if (args.cloudDsn == NULL) {
args.cloud = false;
}
}
} else {
args.cloud = true;
}
} }
int32_t shellReadCommand(TAOS *con, char *command) { int32_t shellReadCommand(TAOS *con, char *command) {
......
...@@ -72,8 +72,7 @@ void shellInit(SShellArguments *_args) { ...@@ -72,8 +72,7 @@ void shellInit(SShellArguments *_args) {
_args->user = TSDB_DEFAULT_USER; _args->user = TSDB_DEFAULT_USER;
} }
if (_args->restful) { if (_args->restful || _args->cloud) {
_args->database = calloc(1, 128);
if (wsclient_handshake()) { if (wsclient_handshake()) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -159,7 +158,7 @@ static int32_t shellRunSingleCommand(TAOS *con, char *command) { ...@@ -159,7 +158,7 @@ static int32_t shellRunSingleCommand(TAOS *con, char *command) {
// Analyse the command. // Analyse the command.
if (regex_match(command, "^[ \t]*(quit|q|exit)[ \t;]*$", REG_EXTENDED | REG_ICASE)) { if (regex_match(command, "^[ \t]*(quit|q|exit)[ \t;]*$", REG_EXTENDED | REG_ICASE)) {
if (args.restful) { if (args.restful || args.cloud) {
close(args.socket); close(args.socket);
} else { } else {
taos_close(con); taos_close(con);
...@@ -290,7 +289,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) { ...@@ -290,7 +289,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) {
printMode = true; // When output to a file, the switch does not work. printMode = true; // When output to a file, the switch does not work.
} }
if (args.restful) { if (args.restful || args.cloud) {
wsclient_query(command); wsclient_query(command);
return; return;
} }
...@@ -1161,12 +1160,39 @@ int wsclient_handshake() { ...@@ -1161,12 +1160,39 @@ int wsclient_handshake() {
key_nonce[i] = rand() & 0xff; key_nonce[i] = rand() & 0xff;
} }
taos_base64_encode(key_nonce, 16, websocket_key, 256); taos_base64_encode(key_nonce, 16, websocket_key, 256);
if (args.token) { if (args.cloud) {
snprintf(request_header, 1024, if (args.cloudDsn == NULL) {
"GET /rest/ws?token=%s HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: " fprintf(stderr, "Cannot read cloud service info\n");
"%s:%d\r\nSec-WebSocket-Key: " return -1;
"%s\r\nSec-WebSocket-Version: 13\r\n\r\n", } else {
args.token, args.host, args.port, websocket_key); char* start = strstr(args.cloudDsn, "http://");
if (start != NULL) {
args.cloudDsn = start + strlen("http://");
} else {
start = strstr(args.cloudDsn, "https://");
if (start != NULL) {
args.cloudDsn = start + strlen("https://");
}
}
char* port = strstr(args.cloudDsn, ":");
if ((port == NULL) || (port + 1) == NULL) {
fprintf(stderr, "Invalid format in TDengine cloud dsn: %s\n", args.cloudDsn);
return -1;
}
port[0] = '\0';
char* token = strstr(port+ strlen(":"), "?token=");
if ((token == NULL) || (token + strlen("?token=")) == NULL) {
fprintf(stderr, "Invalid format in TDengine cloud dsn: %s\n", args.cloudDsn);
return -1;
}
token[0] = '\0';
snprintf(request_header, 1024,
"GET /rest/ws?token=%s HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: "
"%s:%s\r\nSec-WebSocket-Key: "
"%s\r\nSec-WebSocket-Version: 13\r\n\r\n",
token + strlen("?token="), args.cloudDsn, port + strlen(":"), websocket_key);
}
} else { } else {
snprintf(request_header, 1024, snprintf(request_header, 1024,
"GET /rest/ws HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: %s:%d\r\nSec-WebSocket-Key: " "GET /rest/ws HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: %s:%d\r\nSec-WebSocket-Key: "
...@@ -1267,9 +1293,9 @@ int wsclient_send_sql(char *command, WS_ACTION_TYPE type, int id) { ...@@ -1267,9 +1293,9 @@ int wsclient_send_sql(char *command, WS_ACTION_TYPE type, int id) {
switch (type) { switch (type) {
case WS_CONN: case WS_CONN:
cJSON_AddStringToObject(json, "action", "conn"); cJSON_AddStringToObject(json, "action", "conn");
cJSON_AddStringToObject(_args, "user", "root"); cJSON_AddStringToObject(_args, "user", args.user);
cJSON_AddStringToObject(_args, "password", "taosdata"); cJSON_AddStringToObject(_args, "password", args.password);
cJSON_AddStringToObject(_args, "db", ""); cJSON_AddStringToObject(_args, "db", args.database);
break; break;
case WS_QUERY: case WS_QUERY:
...@@ -1322,6 +1348,12 @@ int wsclient_conn() { ...@@ -1322,6 +1348,12 @@ int wsclient_conn() {
} }
if (code->valueint == 0) { if (code->valueint == 0) {
cJSON_Delete(root); cJSON_Delete(root);
if (args.cloud) {
fprintf(stdout, "Successfully connect to cloud service in restful mode\n");
} else {
fprintf(stdout, "Successfully connect to %s in restful mode\n", args.host);
}
return 0; return 0;
} else { } else {
cJSON *message = cJSON_GetObjectItem(root, "message"); cJSON *message = cJSON_GetObjectItem(root, "message");
...@@ -1587,4 +1619,4 @@ void wsclient_query(char *command) { ...@@ -1587,4 +1619,4 @@ void wsclient_query(char *command) {
} }
cJSON_Delete(query); cJSON_Delete(query);
return; return;
} }
\ No newline at end of file
...@@ -54,7 +54,7 @@ static struct argp_option options[] = { ...@@ -54,7 +54,7 @@ static struct argp_option options[] = {
{"pktnum", 'N', "PKTNUM", 0, "Packet numbers used for net test, default is 100."}, {"pktnum", 'N', "PKTNUM", 0, "Packet numbers used for net test, default is 100."},
{"pkttype", 'S', "PKTTYPE", 0, "Choose packet type used for net test, default is TCP. Only speed test could be either TCP or UDP."}, {"pkttype", 'S', "PKTTYPE", 0, "Choose packet type used for net test, default is TCP. Only speed test could be either TCP or UDP."},
{"restful", 'R', 0, 0, "Connect and interact with TDengine use restful."}, {"restful", 'R', 0, 0, "Connect and interact with TDengine use restful."},
{"token", 't', "TOKEN", 0, "The token to use when connecting TDengine's cloud services."}, {0, 'E', "DSN", 0, "The DSN to use when connecting TDengine's cloud services."},
{0}}; {0}};
static error_t parse_opt(int key, char *arg, struct argp_state *state) { static error_t parse_opt(int key, char *arg, struct argp_state *state) {
...@@ -64,21 +64,20 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -64,21 +64,20 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
wordexp_t full_path; wordexp_t full_path;
switch (key) { switch (key) {
case 'h':{ case 'h':
char* tmp = strstr(arg, ":"); if (arg) {
if (tmp == NULL) { args.cloud = false;
arguments->host = arg; args.host = arg;
} else if ((tmp + 1) != NULL) { } else {
arguments->port = atoi(tmp + 1); fprintf(stderr, "Invalid host\n");
tmp[0] = '\0'; return -1;
arguments->host = arg; }
} break;
break;
}
case 'p': case 'p':
break; break;
case 'P': case 'P':
if (arg) { if (arg) {
args.cloud = false;
tsDnodeShellPort = atoi(arg); tsDnodeShellPort = atoi(arg);
p_port = atoi(arg); p_port = atoi(arg);
} else { } else {
...@@ -106,6 +105,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -106,6 +105,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
wordfree(&full_path); wordfree(&full_path);
return -1; return -1;
} }
args.cloud = false;
tstrncpy(configDir, full_path.we_wordv[0], TSDB_FILENAME_LEN); tstrncpy(configDir, full_path.we_wordv[0], TSDB_FILENAME_LEN);
wordfree(&full_path); wordfree(&full_path);
break; break;
...@@ -173,11 +173,17 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { ...@@ -173,11 +173,17 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
case OPT_ABORT: case OPT_ABORT:
arguments->abort = 1; arguments->abort = 1;
break; break;
case 't':
arguments->token = arg;
break;
case 'R': case 'R':
arguments->restful = true; arguments->restful = true;
arguments->cloud = false;
break;
case 'E':
if (arg) {
arguments->cloudDsn = arg;
} else {
fprintf(stderr, "Invalid -E option\n");
return -1;
}
break; break;
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
...@@ -231,8 +237,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -231,8 +237,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
argp_parse(&argp, argc, argv, 0, 0, arguments); argp_parse(&argp, argc, argv, 0, 0, arguments);
if (arguments->token == NULL) {
arguments->port = p_port; if (args.cloudDsn == NULL) {
if (args.cloud) {
args.cloudDsn = getenv("TDENGINE_CLOUD_DSN");
if (args.cloudDsn == NULL) {
args.cloud = false;
}
}
} else {
args.cloud = true;
} }
if (arguments->abort) { if (arguments->abort) {
......
...@@ -76,7 +76,6 @@ SShellArguments args = {.host = NULL, ...@@ -76,7 +76,6 @@ SShellArguments args = {.host = NULL,
.database = NULL, .database = NULL,
.timezone = NULL, .timezone = NULL,
.restful = false, .restful = false,
.token = NULL,
.is_raw_time = false, .is_raw_time = false,
.is_use_passwd = false, .is_use_passwd = false,
.dump_config = false, .dump_config = false,
...@@ -87,7 +86,10 @@ SShellArguments args = {.host = NULL, ...@@ -87,7 +86,10 @@ SShellArguments args = {.host = NULL,
.pktLen = 1000, .pktLen = 1000,
.pktNum = 100, .pktNum = 100,
.pktType = "TCP", .pktType = "TCP",
.netTestRole = NULL}; .netTestRole = NULL,
.cloudDsn = NULL,
.cloud = true,
};
/* /*
* Main function. * Main function.
...@@ -102,35 +104,6 @@ int main(int argc, char* argv[]) { ...@@ -102,35 +104,6 @@ int main(int argc, char* argv[]) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
char* cloud_url = getenv("TDENGINE_CLOUD_URL");
if (cloud_url != NULL) {
char* start = strstr(cloud_url, "http://");
if (start != NULL) {
cloud_url = start + strlen("http://");
} else {
start = strstr(cloud_url, "https://");
if (start != NULL) {
cloud_url = start + strlen("https://");
}
}
char* tmp = last_strstr(cloud_url, ":");
if ((tmp == NULL) && ((tmp + 1) != NULL )) {
fprintf(stderr, "Invalid format in environment variable TDENGINE_CLOUD_URL: %s\n", cloud_url);
exit(EXIT_FAILURE);
} else {
args.port = atoi(tmp + 1);
tmp[0] = '\0';
args.host = cloud_url;
}
}
char* cloud_token = getenv("TDENGINE_CLOUD_TOKEN");
if (cloud_token != NULL) {
args.token = cloud_token;
}
shellParseArgument(argc, argv, &args); shellParseArgument(argc, argv, &args);
if (args.dump_config) { if (args.dump_config) {
...@@ -155,7 +128,7 @@ int main(int argc, char* argv[]) { ...@@ -155,7 +128,7 @@ int main(int argc, char* argv[]) {
exit(0); exit(0);
} }
if (args.restful) { if (args.restful || args.cloud) {
if (tcpConnect()) { if (tcpConnect()) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
......
...@@ -64,8 +64,8 @@ void printHelp() { ...@@ -64,8 +64,8 @@ void printHelp() {
printf("%s%s%s\n", indent, indent, "Packet numbers used for net test, default is 100."); printf("%s%s%s\n", indent, indent, "Packet numbers used for net test, default is 100.");
printf("%s%s\n", indent, "-R"); printf("%s%s\n", indent, "-R");
printf("%s%s%s\n", indent, indent, "Connect and interact with TDengine use restful."); printf("%s%s%s\n", indent, indent, "Connect and interact with TDengine use restful.");
printf("%s%s\n", indent, "-t"); printf("%s%s\n", indent, "-E");
printf("%s%s%s\n", indent, indent, "The token to use when connecting TDengine's cloud services."); printf("%s%s%s\n", indent, indent, "The DSN to use when connecting TDengine's cloud services.");
printf("%s%s\n", indent, "-S"); printf("%s%s\n", indent, "-S");
printf("%s%s%s\n", indent, indent, "Packet type used for net test, default is TCP."); printf("%s%s%s\n", indent, indent, "Packet type used for net test, default is TCP.");
printf("%s%s\n", indent, "-V"); printf("%s%s\n", indent, "-V");
...@@ -80,15 +80,8 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -80,15 +80,8 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
// for host // for host
if (strcmp(argv[i], "-h") == 0) { if (strcmp(argv[i], "-h") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
char* arg = argv[++i]; arguments->cloud = false;
char* tmp = strstr(arg, ":"); arguments->host = argv[++i];
if (tmp == NULL) {
arguments->host = arg;
} else if ((tmp + 1) != NULL) {
arguments->port = atoi(tmp + 1);
tmp[0] = '\0';
arguments->host = arg;
}
} else { } else {
fprintf(stderr, "option -h requires an argument\n"); fprintf(stderr, "option -h requires an argument\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -119,6 +112,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -119,6 +112,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
// for management port // for management port
else if (strcmp(argv[i], "-P") == 0) { else if (strcmp(argv[i], "-P") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
arguments->cloud = false;
arguments->port = atoi(argv[++i]); arguments->port = atoi(argv[++i]);
} else { } else {
fprintf(stderr, "option -P requires an argument\n"); fprintf(stderr, "option -P requires an argument\n");
...@@ -142,6 +136,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -142,6 +136,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
} else if (strcmp(argv[i], "-c") == 0) { } else if (strcmp(argv[i], "-c") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
arguments->cloud = false;
char *tmp = argv[++i]; char *tmp = argv[++i];
if (strlen(tmp) >= TSDB_FILENAME_LEN) { if (strlen(tmp) >= TSDB_FILENAME_LEN) {
fprintf(stderr, "config file path: %s overflow max len %d\n", tmp, TSDB_FILENAME_LEN - 1); fprintf(stderr, "config file path: %s overflow max len %d\n", tmp, TSDB_FILENAME_LEN - 1);
...@@ -225,14 +220,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -225,14 +220,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
} }
else if (strcmp(argv[i], "-R") == 0) { else if (strcmp(argv[i], "-R") == 0) {
arguments->cloud = false;
arguments->restful = true; arguments->restful = true;
} }
else if (strcmp(argv[i], "-t") == 0) { else if (strcmp(argv[i], "-E") == 0) {
if (i < argc - 1) { if (i < argc - 1) {
arguments->token = argv[++i]; arguments->cloudDsn = argv[++i];
} else { } else {
fprintf(stderr, "options -t requires an argument\n"); fprintf(stderr, "options -E requires an argument\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -251,6 +247,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { ...@@ -251,6 +247,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (args.cloudDsn == NULL) {
if (args.cloud) {
args.cloudDsn = getenv("TDENGINE_CLOUD_DSN");
if (args.cloudDsn == NULL) {
args.cloud = false;
}
}
} else {
args.cloud = true;
}
} }
void shellPrintContinuePrompt() { printf("%s", CONTINUE_PROMPT); } void shellPrintContinuePrompt() { printf("%s", CONTINUE_PROMPT); }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册