From cc6e3309c6ae7932102f51381b91dece371b265f Mon Sep 17 00:00:00 2001 From: TwistedTwigleg Date: Mon, 14 Mar 2022 19:11:36 -0400 Subject: [PATCH] Refactor of command line argument parsing to single file (#388) Now command line parsing is broken down into a shared module so it can be reused across samples. This makes samples smaller and reduces bloat. Commit log: * Initial work on simplifying command line parsing * Continued work on simplifying command line parsing * Reformatted samples with, hopefully, the correct clang format setting this times * Another attempt at fixing clang format issues * Adjustments to CommandLineUtils and samples to allow building on Windows and Linux * Adjusted secure_tunnel sample to use AWS String instead of std string * Remove commented out namespace usage in secure_tunnel sample * Adjusted samples command line parser to show input type for commands * Minor command line parsing format fixes * Adjusted based on review feedback * Minor formatting fix * Removed const in main function in samples * Clang format fixes * Added additional command groups * Renamed AddCommonX509Commands utility function --- .../greengrass/basic_discovery/CMakeLists.txt | 2 + samples/greengrass/basic_discovery/main.cpp | 109 +++------ samples/greengrass/ipc/CMakeLists.txt | 2 + samples/greengrass/ipc/main.cpp | 47 +--- .../fleet_provisioning/CMakeLists.txt | 2 + samples/identity/fleet_provisioning/main.cpp | 78 ++---- .../describe_job_execution/CMakeLists.txt | 2 + samples/jobs/describe_job_execution/main.cpp | 70 ++---- samples/mqtt/basic_pub_sub/CMakeLists.txt | 2 + samples/mqtt/basic_pub_sub/main.cpp | 229 +++++------------- samples/mqtt/pkcs11_pub_sub/CMakeLists.txt | 2 + samples/mqtt/pkcs11_pub_sub/main.cpp | 138 +++-------- samples/mqtt/raw_pub_sub/CMakeLists.txt | 2 + samples/mqtt/raw_pub_sub/main.cpp | 145 ++++------- .../secure_tunnel/CMakeLists.txt | 2 + .../secure_tunneling/secure_tunnel/main.cpp | 177 +++++--------- .../tunnel_notification/CMakeLists.txt | 2 + .../tunnel_notification/main.cpp | 65 ++--- samples/shadow/shadow_sync/CMakeLists.txt | 2 + samples/shadow/shadow_sync/main.cpp | 70 ++---- samples/utils/CommandLineUtils.cpp | 174 +++++++++++++ samples/utils/CommandLineUtils.h | 164 +++++++++++++ 22 files changed, 675 insertions(+), 811 deletions(-) create mode 100644 samples/utils/CommandLineUtils.cpp create mode 100644 samples/utils/CommandLineUtils.h diff --git a/samples/greengrass/basic_discovery/CMakeLists.txt b/samples/greengrass/basic_discovery/CMakeLists.txt index ef6c68646..891fe830a 100644 --- a/samples/greengrass/basic_discovery/CMakeLists.txt +++ b/samples/greengrass/basic_discovery/CMakeLists.txt @@ -4,6 +4,8 @@ project(basic-discovery CXX) file(GLOB SRC_FILES "*.cpp" + "../../utils/CommandLineUtils.cpp" + "../../utils/CommandLineUtils.h" ) add_executable(${PROJECT_NAME} ${SRC_FILES}) diff --git a/samples/greengrass/basic_discovery/main.cpp b/samples/greengrass/basic_discovery/main.cpp index 53892aa70..ef367db45 100644 --- a/samples/greengrass/basic_discovery/main.cpp +++ b/samples/greengrass/basic_discovery/main.cpp @@ -14,47 +14,11 @@ #include #include +#include "../../utils/CommandLineUtils.h" + using namespace Aws::Crt; using namespace Aws::Discovery; -static void s_printHelp() -{ - fprintf(stdout, "Usage:\n"); - fprintf( - stdout, - "basic-discovery --region --cert " - " --key --ca_file " - " --thing_name --topic " - " --mode --message " - " --proxy-host --proxy-port \n\n"); - fprintf(stdout, "region: the region for your green grass groups, default us-east-1\n"); - fprintf(stdout, "cert: path to your client certificate in PEM format\n"); - fprintf(stdout, "key: path to your key in PEM format\n"); - fprintf(stdout, "ca_file: ca file to use in verifying TLS connections.\n"); - fprintf(stdout, "\tIt's the path to a CA file in PEM format\n"); - fprintf(stdout, "thing_name: the name of your IOT thing\n"); - fprintf(stdout, "topic: targeted topic. Default is test/topic\n"); - fprintf(stdout, "mode: default both\n"); - fprintf(stdout, "message: message to publish. default 'Hello World'\n"); - fprintf(stdout, "proxy-host: proxy host to use for discovery call. Default is to not use a proxy.\n"); - fprintf(stdout, "proxy-port: proxy port to use for discovery call.\n"); -} - -bool s_cmdOptionExists(char **begin, char **end, const String &option) -{ - return std::find(begin, end, option) != end; -} - -char *s_getCmdOption(char **begin, char **end, const String &option) -{ - char **itr = std::find(begin, end, option); - if (itr != end && ++itr != end) - { - return *itr; - } - return 0; -} - int main(int argc, char *argv[]) { /************************ Setup the Lib ****************************/ @@ -75,50 +39,37 @@ int main(int argc, char *argv[]) String message("Hello World"); /*********************** Parse Arguments ***************************/ - if (!(s_cmdOptionExists(argv, argv + argc, "--cert") && s_cmdOptionExists(argv, argv + argc, "--key") && - s_cmdOptionExists(argv, argv + argc, "--thing_name"))) - { - s_printHelp(); - return 0; - } - - certificatePath = s_getCmdOption(argv, argv + argc, "--cert"); - keyPath = s_getCmdOption(argv, argv + argc, "--key"); - thingName = s_getCmdOption(argv, argv + argc, "--thing_name"); - - if (s_cmdOptionExists(argv, argv + argc, "--ca_file")) + Utils::CommandLineUtils cmdUtils = Utils::CommandLineUtils(); + cmdUtils.RegisterProgramName("basic-discovery"); + cmdUtils.AddCommonMQTTCommands(); + cmdUtils.AddCommonProxyCommands(); + cmdUtils.AddCommonTopicMessageCommands(); + cmdUtils.RemoveCommand("endpoint"); + cmdUtils.RegisterCommand( + "region", "", "The region for your Greengrass groups (optional, default='us-east-1')."); + cmdUtils.RegisterCommand("thing_name", "", "The name of your IOT thing"); + cmdUtils.RegisterCommand( + "mode", "", "Mode options: 'both', 'publish', or 'subscribe' (optional, default='both')."); + const char **const_argv = (const char **)argv; + cmdUtils.SendArguments(const_argv, const_argv + argc); + + if (cmdUtils.HasCommand("help")) { - caFile = s_getCmdOption(argv, argv + argc, "--ca_file"); - } - - if (s_cmdOptionExists(argv, argv + argc, "--region")) - { - region = s_getCmdOption(argv, argv + argc, "--region"); - } - - if (s_cmdOptionExists(argv, argv + argc, "--topic")) - { - topic = s_getCmdOption(argv, argv + argc, "--topic"); - } - - if (s_cmdOptionExists(argv, argv + argc, "--mode")) - { - mode = s_getCmdOption(argv, argv + argc, "--mode"); - } - - if (s_cmdOptionExists(argv, argv + argc, "--message")) - { - message = s_getCmdOption(argv, argv + argc, "--message"); - } - - if (s_cmdOptionExists(argv, argv + argc, "--proxy-host")) - { - proxyHost = s_getCmdOption(argv, argv + argc, "--proxy-host"); + cmdUtils.PrintHelp(); + exit(-1); } - - if (s_cmdOptionExists(argv, argv + argc, "--proxy-port")) + certificatePath = cmdUtils.GetCommandRequired("cert"); + keyPath = cmdUtils.GetCommandRequired("key"); + thingName = cmdUtils.GetCommandRequired("thing_name"); + caFile = cmdUtils.GetCommandOrDefault("ca_file", caFile); + region = cmdUtils.GetCommandOrDefault("region", region); + topic = cmdUtils.GetCommandOrDefault("topic", topic); + mode = cmdUtils.GetCommandOrDefault("mode", mode); + message = cmdUtils.GetCommandOrDefault("message", message); + proxyHost = cmdUtils.GetCommandOrDefault("proxy_host", proxyHost); + if (cmdUtils.HasCommand("proxy_port")) { - String portString = s_getCmdOption(argv, argv + argc, "--proxy-port"); + String portString = cmdUtils.GetCommand("proxy_port"); proxyPort = static_cast(atoi(portString.c_str())); } diff --git a/samples/greengrass/ipc/CMakeLists.txt b/samples/greengrass/ipc/CMakeLists.txt index 6af6170b5..646a7868f 100644 --- a/samples/greengrass/ipc/CMakeLists.txt +++ b/samples/greengrass/ipc/CMakeLists.txt @@ -4,6 +4,8 @@ project(greengrass-ipc CXX) file(GLOB SRC_FILES "*.cpp" + "../../utils/CommandLineUtils.cpp" + "../../utils/CommandLineUtils.h" ) add_executable(${PROJECT_NAME} ${SRC_FILES}) diff --git a/samples/greengrass/ipc/main.cpp b/samples/greengrass/ipc/main.cpp index 03840df8f..fa0356ea1 100644 --- a/samples/greengrass/ipc/main.cpp +++ b/samples/greengrass/ipc/main.cpp @@ -7,35 +7,14 @@ #include +#include "../../utils/CommandLineUtils.h" + using namespace Aws::Crt; using namespace Aws::Greengrass; -static void s_printHelp() -{ - fprintf(stdout, "Usage:\n"); - fprintf(stdout, "greengrass-ipc --topic --message \n\n"); - fprintf(stdout, "topic: targeted topic. Default is test/topic\n"); - fprintf(stdout, "message: message to publish. default 'Hello World'\n"); -} - /* Used to check that the publish has been received so that the demo can exit successfully. */ static std::atomic_bool s_publishReceived(false); -bool s_cmdOptionExists(char **begin, char **end, const String &option) -{ - return std::find(begin, end, option) != end; -} - -char *s_getCmdOption(char **begin, char **end, const String &option) -{ - char **itr = std::find(begin, end, option); - if (itr != end && ++itr != end) - { - return *itr; - } - return 0; -} - int main(int argc, char *argv[]) { /************************ Setup the Lib ****************************/ @@ -48,21 +27,19 @@ int main(int argc, char *argv[]) String message("Hello World"); /*********************** Parse Arguments ***************************/ - if (s_cmdOptionExists(argv, argv + argc, "--help")) - { - s_printHelp(); - return 0; - } + Utils::CommandLineUtils cmdUtils = Utils::CommandLineUtils(); + cmdUtils.RegisterProgramName("greengrass-ipc"); + cmdUtils.AddCommonTopicMessageCommands(); + const char **const_argv = (const char **)argv; + cmdUtils.SendArguments(const_argv, const_argv + argc); - if (s_cmdOptionExists(argv, argv + argc, "--topic")) + if (cmdUtils.HasCommand("help")) { - topic = s_getCmdOption(argv, argv + argc, "--topic"); - } - - if (s_cmdOptionExists(argv, argv + argc, "--message")) - { - message = s_getCmdOption(argv, argv + argc, "--message"); + cmdUtils.PrintHelp(); + exit(-1); } + topic = cmdUtils.GetCommandOrDefault("topic", topic); + message = cmdUtils.GetCommandOrDefault("message", message); /** * Create the default ClientBootstrap, which will create the default diff --git a/samples/identity/fleet_provisioning/CMakeLists.txt b/samples/identity/fleet_provisioning/CMakeLists.txt index c876fd512..52b9fb458 100644 --- a/samples/identity/fleet_provisioning/CMakeLists.txt +++ b/samples/identity/fleet_provisioning/CMakeLists.txt @@ -4,6 +4,8 @@ project(fleet-provisioning CXX) file(GLOB SRC_FILES "*.cpp" + "../../utils/CommandLineUtils.cpp" + "../../utils/CommandLineUtils.h" ) add_executable(${PROJECT_NAME} ${SRC_FILES}) diff --git a/samples/identity/fleet_provisioning/main.cpp b/samples/identity/fleet_provisioning/main.cpp index 9f0a2acc6..b1478b59c 100644 --- a/samples/identity/fleet_provisioning/main.cpp +++ b/samples/identity/fleet_provisioning/main.cpp @@ -32,47 +32,13 @@ #include #include +#include "../../utils/CommandLineUtils.h" + using namespace Aws::Crt; using namespace Aws::Iotidentity; using namespace std::this_thread; // sleep_for, sleep_until using namespace std::chrono; // nanoseconds, system_clock, seconds -static void s_printHelp() -{ - fprintf(stdout, "Usage:\n"); - fprintf( - stdout, - "fleet-provisioning --endpoint --ca_file --cert " - " --key --templateName