diff --git a/.github/docker/ddsrouter/Dockerfile b/.github/docker/ddsrouter/Dockerfile index 544a1d2e6..cd6472a6a 100644 --- a/.github/docker/ddsrouter/Dockerfile +++ b/.github/docker/ddsrouter/Dockerfile @@ -35,9 +35,7 @@ RUN pip3 install \ colcon-mixin \ lxml \ vcstool \ - GitPython \ - pyyaml \ - jsonschema + GitPython WORKDIR /ddsrouter diff --git a/.gitignore b/.gitignore index e2ebcf1a7..0a429aea5 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ log/ docs/rst/_static/css/eprosima-furo.css docs/rst/_static/eprosima-logo-white.png docs/rst/_templates/sidebar/ +docs/resources/examples/ ### Python ### diff --git a/ddsrouter_yaml/CMakeLists.txt b/ddsrouter_yaml/CMakeLists.txt index e3e2414a1..fde575692 100644 --- a/ddsrouter_yaml/CMakeLists.txt +++ b/ddsrouter_yaml/CMakeLists.txt @@ -74,6 +74,37 @@ compile_test_library( "${PROJECT_SOURCE_DIR}/test" # Test directory ) +############################################################################### +# Resources +############################################################################### +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS + "${PROJECT_SOURCE_DIR}/../resources/configurations/ddsrouter_config_schema.json") + +file(READ "${PROJECT_SOURCE_DIR}/../resources/configurations/ddsrouter_config_schema.json" + DDSROUTER_CONFIG_SCHEMA_CONTENT) + +# Split into <=16000-char chunks to work around MSVC C2026 string literal size limit. +# Adjacent string literals are concatenated by the compiler. +string(LENGTH "${DDSROUTER_CONFIG_SCHEMA_CONTENT}" _schema_len) +set(_chunk_size 16000) +set(DDSROUTER_CONFIG_SCHEMA_CHUNKS "") +set(_offset 0) +while(_offset LESS _schema_len) + string(SUBSTRING "${DDSROUTER_CONFIG_SCHEMA_CONTENT}" ${_offset} ${_chunk_size} _chunk) + string(APPEND DDSROUTER_CONFIG_SCHEMA_CHUNKS " R\"json(${_chunk})json\"\n") + math(EXPR _offset "${_offset} + ${_chunk_size}") +endwhile() + +configure_file( + "${PROJECT_SOURCE_DIR}/include/ddsrouter_yaml/DdsRouterConfigSchema.hpp.in" + "${CMAKE_CURRENT_BINARY_DIR}/include/ddsrouter_yaml/DdsRouterConfigSchema.hpp" + @ONLY +) + +target_include_directories(${MODULE_NAME} PUBLIC + $ +) + ############################################################################### # Packaging ############################################################################### diff --git a/ddsrouter_yaml/include/ddsrouter_yaml/DdsRouterConfigSchema.hpp.in b/ddsrouter_yaml/include/ddsrouter_yaml/DdsRouterConfigSchema.hpp.in new file mode 100644 index 000000000..a114ea638 --- /dev/null +++ b/ddsrouter_yaml/include/ddsrouter_yaml/DdsRouterConfigSchema.hpp.in @@ -0,0 +1,18 @@ +// Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +static const char* DDSROUTER_CONFIG_SCHEMA = + @DDSROUTER_CONFIG_SCHEMA_CHUNKS@; diff --git a/ddsrouter_yaml/project_settings.cmake b/ddsrouter_yaml/project_settings.cmake index 6fb1db5f0..40d8da377 100644 --- a/ddsrouter_yaml/project_settings.cmake +++ b/ddsrouter_yaml/project_settings.cmake @@ -37,3 +37,6 @@ set(fastdds_MINIMUM_VERSION "3.0.0") set(MODULE_DEPENDENCIES $<$:iphlpapi$Shlwapi> ${MODULE_FIND_PACKAGES}) + +set(MODULE_CPP_VERSION + C++17) diff --git a/ddsrouter_yaml/src/cpp/YamlReaderConfiguration.cpp b/ddsrouter_yaml/src/cpp/YamlReaderConfiguration.cpp index acfba8669..e54d99fea 100644 --- a/ddsrouter_yaml/src/cpp/YamlReaderConfiguration.cpp +++ b/ddsrouter_yaml/src/cpp/YamlReaderConfiguration.cpp @@ -16,10 +16,12 @@ #include #include #include +#include #include #include +#include namespace eprosima { namespace ddsrouter { @@ -30,6 +32,16 @@ YamlReaderConfiguration::load_ddsrouter_configuration( const Yaml& yml, const CommandlineArgsRouter* args /*= nullptr*/) { + // Ensure the Yaml is valid + ddspipe::yaml::YamlValidator validator = ddspipe::yaml::YamlValidator( + ddspipe::yaml::YamlValidator::InputType::FROM_STRING, + DDSROUTER_CONFIG_SCHEMA); + if (!validator.validate_YAML(yml)) + { + throw eprosima::utils::ConfigurationException( + utils::Formatter() << "Error, the provided yaml file is not a valid ddsrouter configuration."); + } + try { ddspipe::yaml::YamlReaderVersion version; @@ -49,18 +61,24 @@ YamlReaderConfiguration::load_ddsrouter_configuration( case ddspipe::yaml::YamlReaderVersion::V_2_0: case ddspipe::yaml::YamlReaderVersion::V_3_0: case ddspipe::yaml::YamlReaderVersion::V_3_1: - default: - throw eprosima::utils::ConfigurationException( - utils::Formatter() << - "The yaml configuration version " << version << - " is no longer supported. Please update to v5.0."); + utils::Formatter() + << "The yaml configuration version " << version + << " is no longer supported. Please update to " + << ddspipe::yaml::YamlReaderVersion::LATEST << "."); break; case ddspipe::yaml::YamlReaderVersion::V_4_0: - EPROSIMA_LOG_WARNING(DDSROUTER_YAML, - "The yaml configuration version " << version << - " is deprecated and will be removed in a future release. Please update to v5.0."); + EPROSIMA_LOG_WARNING(DDSROUTER_YAML, "The yaml configuration version " + << version << " is deprecated and will be removed in a future release. " + << "Please update to " << ddspipe::yaml::YamlReaderVersion::LATEST << "."); + break; + + default: + // Defensive fallback. With mandatory schema validation enabled, it is not necessary. + throw eprosima::utils::ConfigurationException(utils::Formatter() + << "The yaml configuration version " << version << " is unknown and not supported." + << "Please update to " << ddspipe::yaml::YamlReaderVersion::LATEST << "."); break; } } @@ -69,9 +87,11 @@ YamlReaderConfiguration::load_ddsrouter_configuration( // Get default version version = default_yaml_version(); EPROSIMA_LOG_WARNING(DDSROUTER_YAML, - "No version of yaml configuration given. Using version " << version << " by default. " << - "Add " << ddspipe::yaml::VERSION_TAG << " tag to your configuration in order to not break compatibility " << - "in future releases."); + "No version of yaml configuration given. Using version " + << version << " by default. " + << "Add " << ddspipe::yaml::VERSION_TAG + << " tag to your configuration in order to not break compatibility " + << "in future releases."); } EPROSIMA_LOG_INFO(DDSROUTER_YAML, "Loading DDSRouter configuration with version: " << version << "."); @@ -111,15 +131,15 @@ YamlReaderConfiguration::load_ddsrouter_configuration_from_file( catch (const std::exception& e) { throw eprosima::utils::ConfigurationException( - utils::Formatter() << "Error loading DDSRouter configuration from file: <" << file_path << - "> :\n " << e.what()); + utils::Formatter() << "Error loading DDSRouter configuration from file: <" << file_path + << "> :\n " << e.what()); } if (yml.IsNull()) { throw eprosima::utils::ConfigurationException( - utils::Formatter() << "Error loading DDSRouter configuration from file: <" << file_path << - "> :\n " << "yaml node is null."); + utils::Formatter() << "Error loading DDSRouter configuration from file: <" << file_path + << "> :\n " << "yaml node is null."); } return YamlReaderConfiguration::load_ddsrouter_configuration(yml, args); diff --git a/ddsrouter_yaml/src/cpp/YamlReader_configuration.cpp b/ddsrouter_yaml/src/cpp/YamlReader_configuration.cpp index 87dbe354c..2cccb76a5 100644 --- a/ddsrouter_yaml/src/cpp/YamlReader_configuration.cpp +++ b/ddsrouter_yaml/src/cpp/YamlReader_configuration.cpp @@ -34,7 +34,7 @@ namespace eprosima { namespace ddspipe { namespace yaml { -template <> +template<> void YamlReader::fill( ddsrouter::core::SpecsConfiguration& object, const Yaml& yml, @@ -95,7 +95,7 @@ void YamlReader::fill( } } -template <> +template<> ddsrouter::core::types::ParticipantKind YamlReader::get( const Yaml& yml, const YamlReaderVersion /* version */) @@ -105,7 +105,7 @@ ddsrouter::core::types::ParticipantKind YamlReader::get( *ddsrouter::core::types::ParticipantKindBuilder::get_instance()); } -template <> +template<> std::shared_ptr YamlReader::get>( const Yaml& yml, @@ -141,13 +141,13 @@ YamlReader::get>( YamlReader::get(yml, version)); default: - // Non recheable code + // Non reachable code throw eprosima::utils::ConfigurationException( utils::Formatter() << "Unknown or non valid Participant kind: " << kind << "."); } } -template <> +template<> void YamlReader::fill( core::DdsPipeConfiguration& object, const Yaml& yml, @@ -216,7 +216,7 @@ void YamlReader::fill( } } -template <> +template<> core::DdsPipeConfiguration YamlReader::get( const Yaml& yml, const YamlReaderVersion version) @@ -226,7 +226,7 @@ core::DdsPipeConfiguration YamlReader::get( return object; } -template <> +template<> void YamlReader::fill( ddsrouter::core::DdsRouterConfiguration& object, const Yaml& yml, @@ -241,9 +241,9 @@ void YamlReader::fill( if (!participants_configurations_yml.IsSequence()) { throw eprosima::utils::ConfigurationException( - utils::Formatter() << - "Participant configurations must be specified in an array under tag: " << - COLLECTION_PARTICIPANTS_TAG); + utils::Formatter() + << "Participant configurations must be specified in an array under tag: " + << COLLECTION_PARTICIPANTS_TAG); } for (auto conf : participants_configurations_yml) @@ -251,10 +251,10 @@ void YamlReader::fill( ddsrouter::core::types::ParticipantKind kind = YamlReader::get(conf, PARTICIPANT_KIND_TAG, version); object.participants_configurations.insert( - { - kind, - YamlReader::get>(conf, version) - } + { + kind, + YamlReader::get>(conf, version) + } ); } @@ -293,7 +293,7 @@ void YamlReader::fill( } } -template <> +template<> ddsrouter::core::DdsRouterConfiguration YamlReader::get( const Yaml& yml, const YamlReaderVersion version) diff --git a/ddsrouter_yaml/test/unittest/CMakeLists.txt b/ddsrouter_yaml/test/unittest/CMakeLists.txt index 38cbace2d..acbc6281d 100644 --- a/ddsrouter_yaml/test/unittest/CMakeLists.txt +++ b/ddsrouter_yaml/test/unittest/CMakeLists.txt @@ -19,3 +19,4 @@ # TODO uncomment when new API applied add_subdirectory(configuration) add_subdirectory(participants) +add_subdirectory(ddsrouter_yaml_validator) diff --git a/ddsrouter_yaml/test/unittest/configuration/CMakeLists.txt b/ddsrouter_yaml/test/unittest/configuration/CMakeLists.txt index 3caade216..57971c427 100644 --- a/ddsrouter_yaml/test/unittest/configuration/CMakeLists.txt +++ b/ddsrouter_yaml/test/unittest/configuration/CMakeLists.txt @@ -25,8 +25,10 @@ set(TEST_SOURCES ) set(TEST_LIST - # ddsrouter_configuration_v1_not_supported - # get_ddsrouter_configuration_v2 + error_loading_yaml + configuration_version_not_supported + configuration_version_deprecated + valid_yaml_invalid_config get_ddsrouter_configuration_no_version version_negative_cases number_of_threads @@ -51,11 +53,17 @@ set(TEST_EXTRA_LIBRARIES ddsrouter_core ) +file(GLOB_RECURSE TEST_NEEDED_SOURCES + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + "empty_file.yaml" +) + add_unittest_executable( "${TEST_NAME}" "${TEST_SOURCES}" "${TEST_LIST}" - "${TEST_EXTRA_LIBRARIES}") + "${TEST_EXTRA_LIBRARIES}" + "${TEST_NEEDED_SOURCES}") ##################################### # Yaml DdsRouter Configuration Test # diff --git a/ddsrouter_yaml/test/unittest/configuration/YamlReaderConfigurationTest.cpp b/ddsrouter_yaml/test/unittest/configuration/YamlReaderConfigurationTest.cpp index 79994b2a0..7de5213cc 100644 --- a/ddsrouter_yaml/test/unittest/configuration/YamlReaderConfigurationTest.cpp +++ b/ddsrouter_yaml/test/unittest/configuration/YamlReaderConfigurationTest.cpp @@ -25,89 +25,242 @@ using namespace eprosima; /** - * Test load a whole DDS Router Configuration from yaml node for v1.0 of yaml. + * Test errors loading a whole DDS Router Configuration from yaml files. * * CASES: - * - trivial configuration + * - Non-existent file + * - Empty file */ -// TEST(YamlReaderConfigurationTest, ddsrouter_configuration_v1_not_supported) -// { -// std::vector yml_configurations = -// { -// // trivial configuration -// R"( -// version: v1.0 -// participant1: -// type: "echo" -// participant2: -// type: "echo" -// )", -// }; - -// for (const char* yml_configuration : yml_configurations) -// { -// Yaml yml = YAML::Load(yml_configuration); - -// // Load configuration -// ASSERT_THROW( -// ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration(yml), -// utils::ConfigurationException); -// } -// } +TEST(YamlReaderConfigurationTest, error_loading_yaml) +{ + // Non-existent file + { + try + { + ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration_from_file( + "./non_existent_file.yaml"); + FAIL() << "Expected eprosima::utils::ConfigurationException with " + << "'Error loading DDS Router configuration from yaml'.\n"; + } + catch (const utils::ConfigurationException& e) + { + EXPECT_NE(std::string(e.what()).find("Error loading DDSRouter configuration from file: <"), + std::string::npos) + << "Failed for non-existent file.\nActual message: " << e.what(); + } + catch (const std::exception& e) + { + FAIL() << "Expected eprosima::utils::ConfigurationException but " + << "caught a different exception when loading non-existent file.\n" + << "Actual message: " << e.what(); + } + } + + // Empty file + { + try + { + ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration_from_file("./empty_file.yaml"); + FAIL() << "Expected eprosima::utils::ConfigurationException with " + << "'Error loading DDS Router configuration from yaml'.\n"; + } + catch (const utils::ConfigurationException& e) + { + EXPECT_NE(std::string(e.what()).find("Error loading DDSRouter configuration from file: <"), + std::string::npos) + << "Failed for empty file.\nActual message: " << e.what(); + EXPECT_NE(std::string(e.what()).find("yaml node is null"), std::string::npos) + << "Failed for empty file.\nActual message: " << e.what(); + } + catch (const std::exception& e) + { + FAIL() << "Expected eprosima::utils::ConfigurationException but " + << "caught a different exception when loading empty file.\n" + << "Actual message: " << e.what(); + } + } +} /** - * Test load a whole DDS Router Configuration from yaml node for v2.0 of yaml. + * Test load a whole DDS Router Configuration from yaml node for invalid versions of yaml. * * CASES: - * - trivial configuration - * - ROS common configuration + * - V_1_0 + * - V_2_0 + * - V_3_0 + * - V_3_1 + */ +TEST(YamlReaderConfigurationTest, configuration_version_not_supported) +{ + std::vector yml_versions = + { + "v1.0", + "v2.0", + "v3.0", + "v3.1" + }; + + const char* yml_trivial_config = + { + // trivial configuration + "version: %s\n" + "participants:\n" + " - name: EchoParticipant\n" + " kind: echo\n" + " - name: SimpleParticipant\n" + " kind: local\n" + }; + + for (const char* yml_version : yml_versions) + { + std::string st = yml_trivial_config; + st.replace(st.find("%s"), 2, yml_version); + Yaml yml = YAML::Load(st); + + // Load configuration + try + { + ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration(yml); + FAIL() << "Expected eprosima::utils::ConfigurationException with " + << "'The yaml configuration version ... is no longer supported. Please update to ...'.\n"; + } + catch (const utils::ConfigurationException& e) + { + EXPECT_NE(std::string(e.what()).find("is no longer supported. Please update to"), std::string::npos) + << "Failed for file:\n'" << st << "'\nActual message: " << e.what(); + } + catch (const std::exception& e) + { + FAIL() << "Expected eprosima::utils::ConfigurationException but " + << "caught a different exception for file:\n'" + << st << "'\n" + << "Actual message: " << e.what(); + } + } +} + +/** + * Test load a whole DDS Router Configuration from yaml node for deprecated versions of yaml. + * + * CASES: + * - V_4_0 */ -// TEST(YamlReaderConfigurationTest, get_ddsrouter_configuration_v2) -// { -// std::vector yml_configurations = -// { -// // trivial configuration -// R"( -// version: v2.0 -// participants: -// - name: "P1" -// kind: "echo" -// - name: "P2" -// kind: "echo" -// )", - -// // ROS common configuration -// R"( -// version: v2.0 -// builtin: -// - name: "rt/chatter" -// type: "std_msgs::msg::dds_::String_" -// participants: -// - name: "P1" -// kind: "local" -// domain: 0 -// - name: "P2" -// kind: "local" -// domain: 1 -// - name: "P3" -// kind: "simple" -// domain: 2 -// )", -// }; - -// for (const char* yml_configuration : yml_configurations) -// { -// Yaml yml = YAML::Load(yml_configuration); - -// // Load configuration -// ddsrouter::core::DdsRouterConfiguration configuration_result = -// ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration(yml); - -// // Check is valid -// utils::Formatter error_msg; -// ASSERT_TRUE(configuration_result.is_valid(error_msg)) << error_msg; -// } -// } +TEST(YamlReaderConfigurationTest, configuration_version_deprecated) +{ + std::vector yml_versions = + { + "v4.0" + }; + + const char* yml_trivial_config = + { + // trivial configuration + "version: %s\n" + "participants:\n" + " - name: EchoParticipant\n" + " kind: echo\n" + " - name: SimpleParticipant\n" + " kind: local\n" + }; + + for (const char* yml_version : yml_versions) + { + std::string st = yml_trivial_config; + st.replace(st.find("%s"), 2, yml_version); + Yaml yml = YAML::Load(st); + + // Ensure warning is thrown + eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Warning); // set verbosity to warning + testing::internal::CaptureStderr(); + + ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration(yml); + + eprosima::fastdds::dds::Log::Flush(); + std::string output = testing::internal::GetCapturedStderr(); + ASSERT_NE(output.find("The yaml configuration version"), std::string::npos) // the string is different from not found + << "Failed for file:\n'" << st << "'\n"; + ASSERT_NE(output.find("is deprecated and will be removed in a future release. Please update"), + std::string::npos) + << "Failed for file:\n'" << st << "'\n"; + + eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); // restore verbosity + } +} + + +/** + * Test load a whole DDS Router Configuration from yaml that is not a valid router configuration. + * + * CASES: + * - Duplicated route for the same participant + * - Duplicated topic-route for the same topic + */ +TEST(YamlReaderConfigurationTest, valid_yaml_invalid_config) +{ + std::vector yml_configs = + { + "participants:\n" + " - name: P1\n" + " kind: echo\n" + " - name: P2\n" + " kind: echo\n" + " - name: P3\n" + " kind: echo\n" + "routes:\n" // Duplicated route for the same participant + " - src: P1\n" + " dst:\n" + " - P2\n" + " - src: P1\n" + " dst:\n" + " - P3\n", + + "participants:\n" + " - name: P1\n" + " kind: echo\n" + " - name: P2\n" + " kind: echo\n" + " - name: P3\n" + " kind: echo\n" + "topic-routes:\n" // Duplicated topic-route for the same topic + " - name: HelloWorld\n" + " type: HelloWorld\n" + " routes:\n" + " - src: P1\n" + " dst:\n" + " - P2\n" + " - name: HelloWorld\n" + " type: HelloWorld\n" + " routes:\n" + " - src: P2\n" + " dst:\n" + " - P3\n" + }; + + for (const std::string& st : yml_configs) + { + Yaml yml = YAML::Load(st); + + try + { + ddsrouter::yaml::YamlReaderConfiguration::load_ddsrouter_configuration(yml); + FAIL() << "Expected eprosima::utils::ConfigurationException with " + << "'Error loading DDS Router configuration from yaml'.\n"; + } + catch (const utils::ConfigurationException& e) + { + std::cout << "Error message: " << e.what() << std::endl; + EXPECT_NE(std::string(e.what()).find("Error loading DDS Router configuration from yaml"), std::string::npos) + << "Failed for file:\n'" << st << "'\nActual message: " << e.what(); + } + catch (const std::exception& e) + { + FAIL() << "Expected eprosima::utils::ConfigurationException but " + << "caught a different exception for file:\n'" + << st << "'\n" + << "Actual message: " << e.what(); + } + } +} /** * Do not set Yaml version and get default configuration diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/__init__.py b/ddsrouter_yaml/test/unittest/configuration/empty_file.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/__init__.py rename to ddsrouter_yaml/test/unittest/configuration/empty_file.yaml diff --git a/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/CMakeLists.txt b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/CMakeLists.txt new file mode 100644 index 000000000..cde06694a --- /dev/null +++ b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/CMakeLists.txt @@ -0,0 +1,77 @@ +# Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################# +# DdsRouter Yaml Validator Test # +################################# + +set(TEST_NAME YamlValidatorDdsRouterTest) + + +set(TEST_SOURCES + YamlValidatorDdsRouterTest.cpp + ) + +set(TEST_LIST + validation_passed + validation_failed + ) + +set(TEST_EXTRA_LIBRARIES + yaml-cpp + fastcdr + fastdds + cpp_utils + ddspipe_core + ddspipe_participants + ddspipe_yaml + ) + +configure_file( + "${PROJECT_SOURCE_DIR}/../resources/configurations/ddsrouter_config_schema.json" + "${CMAKE_CURRENT_BINARY_DIR}/ddsrouter_config_schema.json" + COPYONLY +) + +file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/valid_config_files_router/") +file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/invalid_config_files_router/") + +file(GLOB_RECURSE TEST_NEEDED_SOURCES + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + "invalid_config_files_router/*.yaml" + "valid_config_files_router/*.yaml" +) + +file(GLOB GETTING_STARTED_YAMLS + "${PROJECT_SOURCE_DIR}/../docs/resources/getting_started/*.yaml" +) +file(COPY ${GETTING_STARTED_YAMLS} + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/valid_config_files_router/" +) + +file(GLOB EXAMPLES_YAMLS + "${PROJECT_SOURCE_DIR}/../resources/configurations/examples/*.yaml" +) +file(COPY ${EXAMPLES_YAMLS} + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/valid_config_files_router/" +) + +add_unittest_executable( + "${TEST_NAME}" + "${TEST_SOURCES}" + "${TEST_LIST}" + "${TEST_EXTRA_LIBRARIES}" + "${TEST_NEEDED_SOURCES}" +) + diff --git a/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/YamlValidatorDdsRouterTest.cpp b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/YamlValidatorDdsRouterTest.cpp new file mode 100644 index 000000000..cbec9d010 --- /dev/null +++ b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/YamlValidatorDdsRouterTest.cpp @@ -0,0 +1,102 @@ +// Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include +#include + +#include +#include + +using namespace eprosima; +using namespace eprosima::ddspipe::yaml; + +namespace test { +// Paths and files for the tests +std::string schema_path = "./ddsrouter_config_schema.json"; + +// Vectors with the valid and invalid YAML files +std::vector valid_files = []() + { + std::vector files; + for (const auto& entry : std::filesystem::directory_iterator("./valid_config_files_router/")) + { + if (entry.path().extension() == ".yaml") + { + files.push_back(entry.path().generic_string()); + } + } + return files; + }(); + +std::vector invalid_files = []() + { + std::vector files; + for (const auto& entry : std::filesystem::directory_iterator("./invalid_config_files_router/")) + { + if (entry.path().extension() == ".yaml") + { + files.push_back(entry.path().generic_string()); + } + } + return files; + }(); +} // namespace test + +/** + * Test that a set of valid YAML configurations pass the validation + */ +TEST(YamlValidatorDdsRouterTest, validation_passed) +{ + YamlValidator validator = YamlValidator(YamlValidator::InputType::FROM_FILE, test::schema_path); + + // valid files + { + for (std::string st : test::valid_files) + { + Yaml yml = YamlManager::load_file(st); + ASSERT_TRUE(validator.validate_YAML(yml)) << "Failed for file: " << st; + } + } + +} + +/** + * Test that a set of invalid YAML configurations don't pass the validation + */ +TEST(YamlValidatorDdsRouterTest, validation_failed) +{ + YamlValidator validator = YamlValidator(YamlValidator::InputType::FROM_FILE, test::schema_path); + + // invalid files + { + for (std::string st : test::invalid_files) + { + Yaml yml = YamlManager::load_file(st); + // Validate is called with false to prevent filling the output with the specific errors + ASSERT_FALSE(validator.validate_YAML(yml, false)) << "Failed for file: " << st; + } + } +} + +int main( + int argc, + char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/address_no_ip_nor_domain.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/address_no_ip_nor_domain.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/address_no_ip_nor_domain.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/address_no_ip_nor_domain.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/address_no_port.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/address_no_port.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/address_no_port.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/address_no_port.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/builtin_topic_no_name.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/builtin_topic_no_name.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/builtin_topic_no_name.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/builtin_topic_no_name.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/builtin_topic_no_type.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/builtin_topic_no_type.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/builtin_topic_no_type.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/builtin_topic_no_type.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/ds_participant_no_discovery_server_guid.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/ds_participant_no_discovery_server_guid.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/ds_participant_no_discovery_server_guid.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/ds_participant_no_discovery_server_guid.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/ds_participant_no_listening_nor_connection_addresses.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/ds_participant_no_listening_nor_connection_addresses.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/ds_participant_no_listening_nor_connection_addresses.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/ds_participant_no_listening_nor_connection_addresses.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/filter_topic_no_name.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/filter_topic_no_name.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/filter_topic_no_name.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/filter_topic_no_name.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/initial_peers_no_addresses.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/initial_peers_no_addresses.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/initial_peers_no_addresses.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/initial_peers_no_addresses.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_version.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/invalid_version.yaml similarity index 94% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_version.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/invalid_version.yaml index 722484f38..dbfba1bea 100644 --- a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_version.yaml +++ b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/invalid_version.yaml @@ -1,3 +1,5 @@ +version: v4.1 + allowlist: - name: HelloWorldTopic type: HelloWorld diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_participant_kind.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/no_participant_kind.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_participant_kind.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/no_participant_kind.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_participant_name.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/no_participant_name.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/no_participant_name.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/no_participant_name.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/tls_ca_no_private_key_provided_cert.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/tls_ca_no_private_key_provided_cert.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/tls_ca_no_private_key_provided_cert.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/tls_ca_no_private_key_provided_cert.yaml diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/tls_no_ca.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/tls_no_ca.yaml similarity index 100% rename from tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/tls_no_ca.yaml rename to ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/invalid_config_files_router/tls_no_ca.yaml diff --git a/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/valid_config_files_router/docu_example.yaml b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/valid_config_files_router/docu_example.yaml new file mode 100644 index 000000000..7429d1430 --- /dev/null +++ b/ddsrouter_yaml/test/unittest/ddsrouter_yaml_validator/valid_config_files_router/docu_example.yaml @@ -0,0 +1,194 @@ +# Specifications +specs: + threads: 10 + remove-unused-entities: false + discovery-trigger: reader + + qos: + history-depth: 1000 + max-tx-rate: 0 + max-rx-rate: 20 + downsampling: 3 + + logging: + verbosity: info + filter: + error: "DDSPIPE|DDSROUTER" + warning: "DDSPIPE|DDSROUTER" + info: "DDSROUTER" + publish: + enable: true + domain: 84 + topic-name: "DdsRouterLogs" + stdout: true + + monitor: + topics: + enable: true + period: 1000 + domain: 10 + topic-name: "DdsRouterTopicStatistics" + +# XML configurations to load +xml: + + # Load this file as Fast DDS XML configuration + files: + - "./xml_configuration.xml" + + # Load text as Fast DDS XML configuration + raw: | + + + + 1 + + + + +# Relay topic rt/chatter and type std_msgs::msg::dds_::String_ +# Relay topic HelloWorldTopic and type HelloWorld + +builtin-topics: + + - name: rt/chatter + type: std_msgs::msg::dds_::String_ + + - name: HelloWorldTopic + type: HelloWorld + +# Manually configure Topic QoS for a set of participants on a topic + +topics: + + - name: "temperature/*" + type: "temperature/types/*" + qos: + max-tx-rate: 15 + downsampling: 2 + participants: + - Participant0 + - Participant1 + +# Do not allow ROS2 services + +blocklist: + - name: "rr/*" + - name: "rq/*" + + +participants: + +#################### + +# Simple DDS Participant in domain 3 + + - name: Participant0 # Participant Name = Participant0 + + kind: local # Participant Kind = local (= simple) + + domain: 3 # DomainId = 3 + + qos: + + max-rx-rate: 0 # Max Reception Rate = 0 (unlimited) + + downsampling: 1 # Downsampling = 1 + +#################### + +# Simple DDS Participant in domain 7 + + - name: Participant1 # Participant Name = Participant1 + + kind: local # Participant Kind = local (= simple) + + domain: 7 # DomainId = 7 + + qos: + + max-rx-rate: 15 # Max Reception Rate = 15 + +#################### + +# Simple DDS Participant configured with ROS 2 Easy Mode + + - name: Participant2 # Participant Name = Participant2 + + kind: simple # Participant Kind = local (= simple) + + domain: 7 # DomainId = 7 + + ros2-easy-mode: "2.2.2.2" # Remote discovery server address + +#################### + +# Discovery Server DDS Participant with ROS GuidPrefix so a local ROS 2 Client could connect to it +# This Discovery Server will listen in ports 11600 and 11601 in localhost + + - name: ServerROS2 # Participant Name = ServerROS2 + + kind: local-discovery-server # Participant Kind = local-discovery-server + + discovery-server-guid: + id: 1 + ros-discovery-server: true # ROS Discovery Server id => GuidPrefix = 44.53.01.5f.45.50.52.4f.53.49.4d.41 + + listening-addresses: # Local Discovery Server Listening Addresses + - ip: 127.0.0.1 # IP = localhost ; Transport = UDP (by default) + port: 11600 # Port = 11600 + - ip: 127.0.0.1 # IP = localhost + port: 11601 # Port = 11601 + external-port: 11602 # External Port = 11602 + transport: tcp # Transport = TCP + + connection-addresses: + - domain: "localhost" + port: 22000 + +#################### + +# Participant that will communicate with a DDS Router in a different LAN. +# This Participant will work as the remote DDS Router Client, so it sets the connection address of the remote one. + + - name: Wan # Participant Name = Wan + + kind: wan-ds # Participant Kind = Discovery Server WAN + + discovery-server-guid: + id: 2 # Internal WAN Discovery Server id => GuidPrefix = 01.0f.02.00.00.00.00.00.00.00.ca.fe + + connection-addresses: # WAN Discovery Server Connection Addresses + - ip: 8.8.8.8 # IP = 8.8.8.8 + port: 11666 # Port = 11666 + transport: udp # Transport = UDP + + +#################### + +# Participant that will use a user set configuration via QoS Profile. + + - name: xml_participant # Participant Name = xml_participant + + kind: xml + + profile: custom_participant_configuration # Configure participant with this profile + +# Custom generic forwarding route. + +routes: + + - src: Participant0 + dst: + - Participant1 + +# Custom topic forwarding route. + +topic-routes: + + - name: HelloWorld + type: HelloWorld + routes: + - src: Participant1 + dst: + - Participant0 diff --git a/docs/conf.py b/docs/conf.py index 41edf9138..24cbe1f04 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,13 @@ import pathlib import re import requests +import shutil +shutil.copytree( + os.path.join(os.path.dirname(__file__), '..', 'resources', 'configurations', 'examples'), + os.path.join(os.path.dirname(__file__), 'resources', 'examples'), + dirs_exist_ok=True +) PROJECT_NAME = 'DDS Router' COMPRESS_PROJECT_NAME = 'ddsrouter' diff --git a/docs/resources/examples/change_domain.yaml b/docs/resources/examples/change_domain.yaml deleted file mode 100644 index a5f2e05c4..000000000 --- a/docs/resources/examples/change_domain.yaml +++ /dev/null @@ -1,16 +0,0 @@ -############################# -# CHANGE DDS DOMAIN EXAMPLE # -############################# - -# DDS Router participants -participants: - - # DDS Simple Participant for DDS Domain 0 - - name: SimpleParticipant_Domain_0 - kind: local - domain: 0 - - # DDS Simple Participant for DDS Domain 1 - - name: SimpleParticipant_Domain_1 - kind: local - domain: 1 diff --git a/docs/resources/examples/change_domain_allowlist.yaml b/docs/resources/examples/change_domain_allowlist.yaml deleted file mode 100644 index 6fc1a0ddb..000000000 --- a/docs/resources/examples/change_domain_allowlist.yaml +++ /dev/null @@ -1,55 +0,0 @@ -######################################## -# CHANGE DOMAIN WITH ALLOWLIST EXAMPLE # -######################################## - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT DOMAIN 0 -# This participant subscribes to allowlist topics in DDS Domain 0 and listen every message published in such DDS Domain - - - name: SimpleParticipant_domain0 # 3 - kind: local # 4 - domain: 0 # 5 - -################################## -# SIMPLE PARTICIPANT DOMAIN 1 -# This participant subscribes to allowlist topics in DDS Domain 1 and listen every message published in such DDS Domain - - - name: SimpleParticipant_domain1 # 6 - kind: local # 7 - domain: 1 # 8 - - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in two different domains -# and transmit those messages through the other domain. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route to them. - -# 3: New Participant with name . - -# 4: Kind of SimpleParticipant_domain0: . -# LAN UDP communication with default simple multicast discovery. - -# 5: SimpleParticipant_domain0 will use DDS Domain ID <0>. - -# 6: New Participant with name . - -# 7: Kind of SimpleParticipant_domain1: . - -# 8: SimpleParticipant_domain1 will use DDS Domain ID <1>. diff --git a/docs/resources/examples/echo.yaml b/docs/resources/examples/echo.yaml deleted file mode 100644 index 2cc1e5e6a..000000000 --- a/docs/resources/examples/echo.yaml +++ /dev/null @@ -1,62 +0,0 @@ -################ -# ECHO EXAMPLE # -################ - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in specific domain and listen every message published there - - - name: SimpleParticipant # 3 - kind: local # 4 - domain: 0 # 5 - -################################## -# ECHO PARTICIPANT -# This Participant will print in stdout every message received by the other Participants, as well as discovery information - - - name: EchoParticipant # 6 - kind: echo # 7 - discovery: true # 8 - data: true # 9 - verbose: true # 10 - - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to print the received -# messages in stdout. Information regarding discovery events is also printed to stdout. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route them. - -# 3: New Participant with name . - -# 4: Kind of SimpleParticipant: . -# LAN UDP communication with default simple multicast discovery. - -# 5: SimpleParticipant will use DDS Domain ID <0>. - -# 6: New Participant with name . - -# 7: Kind of EchoParticipant: . - -# 8: Print a trace to stdout every time an Endpoint is discovered. - -# 9: Print a trace to stdout every time a new data message arrives to the router. - -# 10: Display verbose information regarding received messages (receiver endpoint_guid and data payload). diff --git a/docs/resources/examples/forwarding_routes.yaml b/docs/resources/examples/forwarding_routes.yaml deleted file mode 100644 index 02e38fe2d..000000000 --- a/docs/resources/examples/forwarding_routes.yaml +++ /dev/null @@ -1,107 +0,0 @@ -###################### -# FORWARDING ROUTES # -###################### - -############## -# PARTICIPANTS -participants: # 1 - -#################### -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in domain 0. - - - name: SimpleParticipant_0 # 2 - kind: local # 3 - domain: 0 # 4 - -#################### -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in domain 1. - - - name: SimpleParticipant_1 - kind: local - domain: 1 - - -################ -# GENERIC ROUTES -routes: # 5 - -####### -# ROUTE -# This participant will forward the data it receives to -# SimpleParticipant_1 - - src: SimpleParticipant_0 # 6 - dst: # 7 - - SimpleParticipant_1 # 8 - -####### -# ROUTE -# This participant will not forward the data it receives. - - src: SimpleParticipant_1 # 10 - - -############## -# TOPIC ROUTES -topic-routes: # 11 - - - name: Circle # 12 - type: Configuration # 13 - - routes: # 14 - -############# -# TOPIC ROUTE -# This participant will forward the data it receives on -# topic Circle to SimpleParticipant_0. - - src: SimpleParticipant_1 # 15 - dst: # 16 - - SimpleParticipant_0 # 17 - -############# -# TOPIC ROUTE -# This participant will not forward the data it receives -# on topic Circle. - - src: SimpleParticipant_0 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# to DDS Domain 1. -# The communication is in both directions. - -# 1: List the internal participants of the router. - -# 2: New Participant with name . - -# 3: Kind of SimpleParticipant_0: . -# LAN UDP communication with default simple multicast discovery. - -# 4: SimpleParticipant_0 will use DDS Domain ID <0>. - -# 5: List the generic forwarding routes between the router's internal participants. - -# 6: New forwarding route for SimpleParticipant_0. - -# 7: List the participants SimpleParticipant_0 will forward messages to. - -# 8: SimpleParticipant_0 will forward messages to SimpleParticipant_1. - -# 10: New forwarding route for SimpleParticipant_0. -# Since it doesn't have a dst tag, it will not forward messages to any participant. - -# 11: List the topic forwarding routes between the router's internal participants. - -# 12: New topic forwarding route for topic Circle. - -# 13: The type of the topic Circle for this topic forwarding route to apply must be ShapeType. - -# 14: List the topic forwarding route for topic Circle. - -# 15: New topic forwarding route for SimpleParticipant_0 on topic Circle. - -# 16: List the participants SimpleParticipant_1 will forward messages to on topic Circle. - -# 17: SimpleParticipant_1 will forward messages to SimpleParticipant_0 on topic Circle. diff --git a/docs/resources/examples/repeater_client.yaml b/docs/resources/examples/repeater_client.yaml deleted file mode 100644 index 5196da660..000000000 --- a/docs/resources/examples/repeater_client.yaml +++ /dev/null @@ -1,60 +0,0 @@ -########################### -# REPEATER CLIENT EXAMPLE # -########################### - -################################## -# ALLOWED TOPICS -# Allowing ROS2 HelloWorld demo_nodes - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there - - - name: SimpleROS2 # 2 - kind: local # 3 - domain: 0 # 4 - -################################## -# WAN CLIENT -# This participant will subscribe to topics in allowlist using Initial Peers Participant - - - name: Client # 5 - kind: wan # 6 - connection-addresses: - - domain: "server.domain.com" - port: 11666 - transport: tcp - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topic -# rt/chatter from ROS2 demo_nodes, and to transmit these messages through a WAN Participant (configured as Client) -# to another DDS Router (this configuration is independent of the remote Participant being repeater or not). -# The other direction of communication is also possible; receive messages at the WAN Participant and locally -# publish them in domain 0. - -# 1: Allow ROS 2 specific Topic Name with type . -# Insert new topics in order to route them. - -# 2: New Participant with name . - -# 3: Kind of SimpleROS2: . -# LAN UDP communication with default simple multicast discovery. -# Remember that every ROS 2 Node relays the middleware communication to DDS, as a standard Participant. - -# 4: SimpleROS2 will use DDS Domain ID <0>. - -# 5: New Participant with name . - -# 6: Kind of Client: . - -# 7: Add the configuration to connect with the WAN Repeater Participant raised in the other side. diff --git a/docs/resources/examples/repeater_server.yaml b/docs/resources/examples/repeater_server.yaml deleted file mode 100644 index 15eb9af9a..000000000 --- a/docs/resources/examples/repeater_server.yaml +++ /dev/null @@ -1,49 +0,0 @@ -########################### -# REPEATER SERVER EXAMPLE # -########################### - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# WAN SERVER REPEATER -# This participant will repeat the messages that arrive to it. - - - name: RepeaterParticipant # 3 - kind: wan # 4 - repeater: true # 5 - listening-addresses: - - domain: "server.domain.com" - port: 11666 - transport: tcp - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# through a WAN Participant (configured as Server) to another WAN Participant. -# The other direction of communication is also possible; receive messages at the WAN Participant and locally -# publish them in domain 0. -# Server specifies which DDS Router starts the communication with the other, and after communication has been -# established, both routers behave in the same way. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route them. - -# 3: New Participant with name . - -# 4: Kind of RepeaterParticipant: . -# WAN communication with other DDS Routers. - -# 5: RepeaterParticipant will repeat messages that arrive to it to the rest of DDS Routers connected. diff --git a/docs/resources/examples/ros_discovery_client.yaml b/docs/resources/examples/ros_discovery_client.yaml deleted file mode 100644 index f50ea6fd4..000000000 --- a/docs/resources/examples/ros_discovery_client.yaml +++ /dev/null @@ -1,74 +0,0 @@ -####################################### -# ROS DISCOVERY SERVER CLIENT EXAMPLE # -####################################### - -################################## -# ALLOWED TOPICS -# Allowing ROS2 HelloWorld demo_nodes - -allowlist: - - name: rt/chatter # 1 - type: std_msgs::msg::dds_::String_ # 1 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there - - - name: SimpleROS2 # 2 - kind: local # 3 - domain: 0 # 4 - -################################## -# ROS DISCOVERY CLIENT -# This participant will subscribe to topics in allowlist using Discovery Server protocol as Super Client - - - name: ClientROS2 # 5 - kind: local-discovery-server # 6 - connection-addresses: # 7 - - domain: localhost # 8 - port: 11888 # 9 - # 10 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topic -# rt/chatter from ROS2 demo_nodes, and to transmit these messages through a Discovery Server (configured as -# Super Client) to another Discovery Server (configured as Server). -# The other direction of communication is also possible; receive messages at the Discovery Server and locally -# publish them in domain 0. - -# 1: Allow ROS 2 specific Topic Name with type . -# Insert new topics in order to route them. - -# 2: New Participant with name . - -# 3: Kind of SimpleROS2: . -# LAN UDP communication with default simple multicast discovery. -# Remember that every ROS 2 Node relays the middleware communication to DDS, as a standard Participant. - -# 4: SimpleROS2 will use DDS Domain ID <0>. - -# 5: New Participant with name . - -# 6: Kind of ClientROS2: . -# If not listening address are set for this Participant, it acts as SuperClient of Discovery Server Discovery Protocol. - -# 7: Use the default Discovery Server ROS 2 GuidPrefix <44.53. .5f.45.50.52.4f.53.49.4d.41>. - -# 8: Set this Discovery Server GuidPrefix to <44.53.02.5f.45.50.52.4f.53.49.4d.41>. - -# 9: Add the addresses where this Client will try to reach a Discovery Server. - -# 10: Connect to a Discovery Server in IP localhost listening. This domain will be translated as ip: "127.0.0.1" - -# 11: Discovery Server listening port is 11888. - -# 12: This is the same configuration as the result using Fast DDS environment variable: -# $> export ROS_DISCOVERY_SERVER=";127.0.0.1:11888" -# Add every other address where trying to reach this same remote Discovery Server, -# or add every other Discovery Server connection required. diff --git a/docs/resources/examples/ros_discovery_server.yaml b/docs/resources/examples/ros_discovery_server.yaml deleted file mode 100644 index 57b8db5da..000000000 --- a/docs/resources/examples/ros_discovery_server.yaml +++ /dev/null @@ -1,72 +0,0 @@ -################################ -# ROS DISCOVERY SERVER EXAMPLE # -################################ - -################################## -# ALLOWED TOPICS -# Allowing ROS2 HelloWorld demo_nodes topic - -allowlist: - - name: rt/chatter # 1 - type: std_msgs::msg::dds_::String_ # 1 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there - - - name: SimpleROS2 # 2 - kind: local # 3 - domain: 0 # 4 - -################################## -# ROS DISCOVERY SERVER -# This participant will subscribe to topics in allowlist using Discovery Server protocol as Server - - - name: ServerROS2 # 5 - kind: local-discovery-server # 6 - listening-addresses: # 7 - - domain: localhost # 8 - port: 11888 # 9 - # 10 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topic -# rt/chatter from ROS2 demo_nodes, and to transmit these messages through a Discovery Server (configured as -# Server) to another Discovery Server. -# The other direction of communication is also possible; receive messages at the Discovery Server and locally -# publish them in domain 0. - -# 1: Allow DDS ROS 2 specific Topic Name with type . -# Insert new topics in order to route them. - -# 2: New Participant with name . - -# 3: Kind of SimpleROS2: . -# LAN UDP communication with default simple multicast discovery. -# Remember that every ROS 2 Node relays the middleware communication to DDS, as a standard Participant. - -# 5: New Participant with name . - -# 6: Kind of ServerROS2: . -# This kind of Participant uses Discovery Server as discovery protocol. - -# 7: Use the default Discovery Server ROS 2 GuidPrefix <44.53. .5f.45.50.52.4f.53.49.4d.41> for ServerROS2. - -# 8: Set this Discovery Server GuidPrefix to <44.53.01.5f.45.50.52.4f.53.49.4d.41> for ServerROS2. - -# 9: Add the interfaces where this Discovery Server will listen for client discovery traffic. - -# 10: Listen in IP localhost(127.0.0.1) for remote discovery traffic -# This IP must be set to the IP of the host where this DDS Router will run. - -# 11: Listen in port 11888 - -# 12: This configuration is equal to create a Discovery Server with Fast DDS CLI using command: -# $> fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888 -# Add every other address where this Discovery Server will listen. diff --git a/docs/resources/examples/wan_client.yaml b/docs/resources/examples/wan_client.yaml deleted file mode 100644 index 344c140f7..000000000 --- a/docs/resources/examples/wan_client.yaml +++ /dev/null @@ -1,84 +0,0 @@ -###################### -# WAN CLIENT EXAMPLE # -###################### - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 1 and listen every message published there - - - name: SimpleParticipant # 3 - kind: local # 4 - domain: 1 # 5 - -################################## -# WAN CLIENT -# This participant will subscribe to topics in allowlist and connect with the server through Initial Peers. - - - name: WANClient # 6 - kind: wan # 7 - connection-addresses: # 8 - - ip: 1.1.1.1 # 9 - port: 11666 - listening-addresses: # 10 - - ip: 2.2.2.2 # 11 - port: 11670 # 12 - transport: udp # 13 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 1 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# through a WAN Participant (configured as Client) to another WAN Participant. -# The other direction of communication is also possible; receive messages at the WAN Participant and locally -# publish them in domain 1. -# Client specifies which DDS Router starts the communication with the other, and after communication has been -# established, both routers behave in the same way. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route them. - -# 3: New Participant with name . - -# 4: Kind of SimpleParticipant: . -# LAN UDP communication with default simple multicast discovery. - -# 5: SimpleParticipant will use DDS Domain ID <1>. - -# 6: New Participant with name . - -# 7: Kind of WANClient: . -# WAN communication with another DDS Router. - -# 8: Add the addresses where to reach the remote DDS Routers that will connect to. -# Add as many connection-addresses as needed. - -# 9: Connect to a WAN Participant in IP <1.1.1.1> listening in port 11666 over UDP transport (default). -# This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. -# Add every other address where trying to reach this same remote WAN Server. - -# 10: Add the interfaces where this Participant will listen in WAN. -# This is only needed if Remote WAN Server is using only UDP. -# Add as many listening-addresses as needed. - -# 11: Listen in public IP (2.2.2.2) for remote traffic. -# This IP must be set to the public IP of the host where this DDS Router will run. - -# 12: Listening port is 11670. -# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network -# router to this host to the same port. - -# 13: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/wan_ds_client.yaml b/docs/resources/examples/wan_ds_client.yaml deleted file mode 100644 index 27192244f..000000000 --- a/docs/resources/examples/wan_ds_client.yaml +++ /dev/null @@ -1,84 +0,0 @@ -####################################### -# WAN DISCOVERY SERVER CLIENT EXAMPLE # -####################################### - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 1 and listen every message published there - - - name: SimpleParticipant # 3 - kind: local # 4 - domain: 1 # 5 - -################################## -# WAN CLIENT -# This participant will subscribe to topics in allowlist using Discovery Server protocol as SuperClient. - - - name: WANClient # 6 - kind: wan-ds # 7 - connection-addresses: # 8 - - ip: 1.1.1.1 # 9 - port: 11666 - listening-addresses: # 10 - - ip: 2.2.2.2 # 11 - port: 11670 # 12 - transport: udp # 13 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 1 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# through a Discovery Server WAN Participant (configured as Super Client) to another Discovery Server WAN Participant. -# The other direction of communication is also possible; receive messages at the Discovery Server WAN Participant and locally -# publish them in domain 1. -# Client specifies which DDS Router starts the communication with the other, and after communication has been -# established, both routers behave in the same way. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route them. - -# 3: New Participant with name . - -# 4: Kind of SimpleParticipant: . -# LAN UDP communication with default simple multicast discovery. - -# 5: SimpleParticipant will use DDS Domain ID <1>. - -# 6: New Participant with name . - -# 7: Kind of WANClient: . -# WAN communication with another DDS Router via Discovery Server. - -# 8: Add the addresses where to reach the remote DDS Routers that will connect to. -# Add as many connection-addresses as needed. - -# 9: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11666 over UDP transport (default). -# This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. -# Add every other address where trying to reach this same remote WAN Discovery Server. - -# 10: Add the interfaces where this Participant will listen in WAN. -# This is only needed if Remote WAN Server is using only UDP. -# Add as many listening-addresses as needed. - -# 11: Listen in public IP (2.2.2.2) for remote traffic. -# This IP must be set to the public IP of the host where this DDS Router will run. - -# 12: Listening port is 11670. -# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network -# router to this host to the same port. - -# 13: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/wan_ds_server.yaml b/docs/resources/examples/wan_ds_server.yaml deleted file mode 100644 index 79316633a..000000000 --- a/docs/resources/examples/wan_ds_server.yaml +++ /dev/null @@ -1,73 +0,0 @@ -####################################### -# WAN DISCOVERY SERVER SERVER EXAMPLE # -####################################### - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there - - - name: SimpleParticipant # 3 - kind: local # 4 - domain: 0 # 5 - -################################## -# WAN SERVER -# This participant will subscribe to topics in allowlist using Discovery Server protocol as Server - - - name: WANServer # 6 - kind: wan-ds # 7 - listening-addresses: # 8 - - ip: 1.1.1.1 # 9 - port: 11666 # 10 - transport: udp # 11 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# through a Discovery Server WAN Participant (configured as Server) to another Discovery Server WAN Participant. -# The other direction of communication is also possible; receive messages at the Discovery Server WAN Participant -# and locally publish them in domain 0. -# Server specifies which DDS Router starts the communication with the other, and after communication has been -# established, both routers behave in the same way. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route them. - -# 3: New Participant with name . - -# 4: Kind of SimpleParticipant: . -# LAN UDP communication with default simple multicast discovery. - -# 5: SimpleParticipant will use DDS Domain ID <0>. - -# 6: New Participant with name . - -# 7: Kind of WANServer: . -# WAN communication with another DDS Router via Discovery Server. - -# 8: Add the interfaces where this Participant will listen in WAN. -# Add as many listening-addresses as needed. - -# 9: Listen in public IP (1.1.1.1) for remote traffic. -# This IP must be set to the public IP of the host where this DDS Router will run. - -# 10: Listening port is 11666. -# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network -# router to this host to the same port. - -# 11: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/wan_server.yaml b/docs/resources/examples/wan_server.yaml deleted file mode 100644 index 02c2bce14..000000000 --- a/docs/resources/examples/wan_server.yaml +++ /dev/null @@ -1,73 +0,0 @@ -###################### -# WAN SERVER EXAMPLE # -###################### - -################################## -# ALLOWED TOPICS -# Allowing FastDDS and ROS2 HelloWorld demo examples topics - -allowlist: - - name: HelloWorldTopic # 1 - - name: rt/chatter # 2 - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there - - - name: SimpleParticipant # 3 - kind: local # 4 - domain: 0 # 5 - -################################## -# WAN SERVER -# This participant will subscribe to topics in allowlist and connect to clients through Initial Peers. - - - name: WANServer # 6 - kind: wan # 7 - listening-addresses: # 8 - - ip: 1.1.1.1 # 9 - port: 11666 # 10 - transport: udp # 11 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# through a WAN Participant (configured as Server) to another WAN Participant. -# The other direction of communication is also possible; receive messages at the WAN Participant and locally -# publish them in domain 0. -# Server specifies which DDS Router starts the communication with the other, and after communication has been -# established, both routers behave in the same way. - -# 1: Allow DDS Topic Name with type . - -# 2: Insert new topics in order to route them. - -# 3: New Participant with name . - -# 4: Kind of SimpleParticipant: . -# LAN UDP communication with default simple multicast discovery. - -# 5: SimpleParticipant will use DDS Domain ID <0>. - -# 6: New Participant with name . - -# 7: Kind of WANServer: . -# WAN communication with another DDS Router. - -# 8: Add the interfaces where this Participant will listen in WAN. -# Add as many listening-addresses as needed. - -# 9: Listen in public IP (1.1.1.1) for remote traffic. -# This IP must be set to the public IP of the host where this DDS Router will run. - -# 10: Listening port is 11666. -# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network -# router to this host to the same port. - -# 11: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/xml.yaml b/docs/resources/examples/xml.yaml deleted file mode 100644 index 12a6c4be9..000000000 --- a/docs/resources/examples/xml.yaml +++ /dev/null @@ -1,71 +0,0 @@ -###################### -# XML EXAMPLE # -###################### - -################################## -# XML CONFIGURATION -xml: # 1 - files: - - "./xml_configuration.xml" # 2 - raw: | # 3 - - - - 1 - - - - -################################## -# PARTICIPANTS -participants: - -################################## -# SIMPLE PARTICIPANT -# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there - - - name: SimpleParticipant # 6 - kind: local # 7 - domain: 0 # 8 - -################################## -# WAN SERVER -# This participant will subscribe to topics in allowlist and connect to clients through Initial Peers. - - - name: XMLParticipant # 9 - kind: xml # 10 - profile: custom_participant_configuration # 11 - -################################## -# CONFIGURATION DESCRIPTION - -# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics -# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages -# to DDS Domain 1. -# The communication is in both directions. - -# 1: Configure how to load XML configurations. - -# 2: Load profiles from every xml file in list. - -# 3: Read the next string as XML and load profiles from it. - -# 4: Allow DDS Topic Name with type . - -# 5: Insert new topics in order to route them. - -# 6: New Participant with name . - -# 7: Kind of SimpleParticipant: . -# LAN UDP communication with default simple multicast discovery. - -# 8: SimpleParticipant will use DDS Domain ID <0>. - -# 9: New Participant with name . - -# 10: Kind of XMLParticipant: . -# XML configuration - -# 11: Profile QoS to create Participant is custom_participant_configuration -# This participant will be configured following such profile QoS. -# In this case, the profile only configures the domain to be 1 diff --git a/docs/rst/developer_manual/installation/sources/linux.rst b/docs/rst/developer_manual/installation/sources/linux.rst index f85fdc8a1..e5dd55cdc 100644 --- a/docs/rst/developer_manual/installation/sources/linux.rst +++ b/docs/rst/developer_manual/installation/sources/linux.rst @@ -41,8 +41,6 @@ installed in the system: * :ref:`cmake_gcc_pip_wget_git_sl` * :ref:`colcon_install` [optional] * :ref:`gtest_sl` [for test only] -* :ref:`py_yaml` [for YAML Validator only] -* :ref:`json_schema` [for YAML Validator only] .. _cmake_gcc_pip_wget_git_sl: diff --git a/docs/rst/developer_manual/installation/sources/windows.rst b/docs/rst/developer_manual/installation/sources/windows.rst index 5988510c4..09442615e 100644 --- a/docs/rst/developer_manual/installation/sources/windows.rst +++ b/docs/rst/developer_manual/installation/sources/windows.rst @@ -44,8 +44,6 @@ installed in the system: * :ref:`windows_sources_cmake_pip3_wget_git` * :ref:`windows_sources_colcon_install` [optional] * :ref:`windows_sources_gtest` [for test only] -* :ref:`windows_py_yaml` [for YAML Validator only] -* :ref:`windows_json_schema` [for YAML Validator only] .. _windows_sources_visual_studio: diff --git a/docs/rst/examples/wan_example.rst b/docs/rst/examples/wan_example.rst index 34989dfaa..0489f97d0 100644 --- a/docs/rst/examples/wan_example.rst +++ b/docs/rst/examples/wan_example.rst @@ -60,7 +60,7 @@ In order to create a WAN Participant Client, check the configuration file .. literalinclude:: ../../resources/examples/wan_client.yaml :language: yaml - :lines: 29-37 + :lines: 29-38 Execute example diff --git a/docs/rst/notes/previous_versions/v0.4.0.rst b/docs/rst/notes/previous_versions/v0.4.0.rst index 309545ead..97fc992df 100644 --- a/docs/rst/notes/previous_versions/v0.4.0.rst +++ b/docs/rst/notes/previous_versions/v0.4.0.rst @@ -4,7 +4,7 @@ Version v0.4.0 This release includes the following **features**: -* New :ref:`yaml_validator`, a simple tool to assert the correctness of DDS Router configuration files. +* New YAML validator, a simple tool to assert the correctness of DDS Router configuration files. * New :ref:`user_manual_user_interface_version_argument` to show the current version of DDS Router. This release includes the following **improvementes**: diff --git a/docs/rst/user_manual/configuration.rst b/docs/rst/user_manual/configuration.rst index 55ddce904..d58d1600e 100644 --- a/docs/rst/user_manual/configuration.rst +++ b/docs/rst/user_manual/configuration.rst @@ -705,8 +705,8 @@ Network Address Network Addresses are elements that can be configured for specific Participants. An Address is defined by: -* *IP*: IP of the host (public IP in case of WAN communication). -* *Port*: Port where the Participant is listening. +* *IP*: IP of the host (public IP in case of WAN communication). This field is mandatory if ``domain`` is not specified. +* *Port*: Port where the Participant is listening. This field is mandatory. * *External Port*: Public port accessible for external entities (only for TCP listening-addresses). * *Transport Protocol*: ``UDP`` or ``TCP``. If it is not set, it would be chosen by default depending on the Participant Kind. @@ -1078,11 +1078,11 @@ A complete example of all the configurations described on this page can be found # Simple DDS Participant configured with ROS 2 Easy Mode - - name: Participant1 # Participant Name = Participant1 + - name: Participant2 # Participant Name = Participant2 kind: simple # Participant Kind = local (= simple) - domain: 7 # DomainId = 7 + domain: 7 # DomainId = 7 ros2-easy-mode: "2.2.2.2" # Remote discovery server address diff --git a/docs/rst/user_manual/yaml_validator.rst b/docs/rst/user_manual/yaml_validator.rst index 5134624bb..70580f53e 100644 --- a/docs/rst/user_manual/yaml_validator.rst +++ b/docs/rst/user_manual/yaml_validator.rst @@ -7,6 +7,12 @@ YAML Validator ############## +.. warning:: + + **DEPRECATED** + + This standalone YAML Validator tool is deprecated. + Configuration files used to launch a DDS-Router instance need to follow a specific structure, which is extensively described along section :ref:`user_manual_configuration`. The *YAML Validator tool* has been developed for the sole purpose of validating user-defined configuration files in an easy manner. diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json b/resources/configurations/ddsrouter_config_schema.json similarity index 56% rename from tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json rename to resources/configurations/ddsrouter_config_schema.json index 46e01806b..ad4d89559 100644 --- a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json +++ b/resources/configurations/ddsrouter_config_schema.json @@ -6,15 +6,20 @@ "type":"object", "additionalProperties":false, "properties":{ - "threads":{ - "type":"integer" - }, "version":{ "type":"string", "enum":[ - "v3.0" + "v1.0", + "v2.0", + "v3.0", + "v3.1", + "v4.0", + "v5.0" ] }, + "specs":{ + "$ref":"#/definitions/SpecsConfig" + }, "allowlist":{ "type":"array", "items":{ @@ -33,6 +38,24 @@ "$ref":"#/definitions/TopicBuiltins" } }, + "routes":{ + "type":"array", + "items":{ + "$ref":"#/definitions/RouteConfig" + } + }, + "topic-routes":{ + "type":"array", + "items":{ + "$ref":"#/definitions/TopicRouteConfig" + } + }, + "topics":{ + "type":"array", + "items":{ + "$ref":"#/definitions/ManualTopic" + } + }, "participants":{ "type":"array", "minItems":1, @@ -42,14 +65,194 @@ "uniqueKeys":[ "/name" ] + }, + "xml":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "raw":{ + "type":"string" + }, + "files":{ + "type":"array", + "minItems":1, + "items":{ + "type":"string" + } + } + }, + "anyOf":[ + { + "required":[ + "raw" + ] + }, + { + "required":[ + "files" + ] + } + ] } }, "required":[ - "version", "participants" ], "title":"BaseObject" }, + "SpecsConfig":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "threads":{ + "type":"integer", + "minimum": 0 + }, + "remove-unused-entities":{ + "type":"boolean" + }, + "qos":{ + "$ref":"#/definitions/QOS" + }, + "discovery-trigger":{ + "type":"string", + "pattern":"^([Rr][Ee][Aa][Dd][Ee][Rr]|[Ww][Rr][Ii][Tt][Ee][Rr]|[Aa][Nn][Yy]|[Nn][Oo][Nn][Ee])$" + }, + "logging":{ + "$ref":"#/definitions/LogConfig" + }, + "monitor":{ + "$ref":"#/definitions/MonitorConfig" + } + } + }, + "QOS":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "durability":{ + "type":"boolean" + }, + "reliability":{ + "type":"boolean" + }, + "ownership":{ + "type":"boolean" + }, + "partitions":{ + "type":"boolean" + }, + "history-depth":{ + "type":"integer", + "minimum":0 + }, + "keyed":{ + "type":"boolean" + }, + "max-tx-rate":{ + "type":"number", + "minimum": 0 + }, + "max-rx-rate":{ + "type":"number", + "minimum": 0 + }, + "downsampling":{ + "type":"integer", + "minimum": 1 + } + }, + "title": "QOS" + }, + "LogConfig":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "publish":{ + "type":"object", + "additionalProperties": false, + "properties": { + "enable":{ + "type":"boolean" + }, + "domain":{ + "$ref":"#/definitions/DdsDomain" + }, + "topic-name":{ + "type":"string" + } + }, + "required": [ + "enable" + ] + }, + "stdout":{ + "type":"boolean" + }, + "verbosity":{ + "type":"string", + "enum":[ + "info", + "warning", + "error" + ] + }, + "filter":{ + "type":"object", + "additionalProperties": false, + "properties": { + "info":{ + "type":"string" + }, + "warning":{ + "type":"string" + }, + "error":{ + "type":"string" + } + } + } + } + }, + "MonitorConfig":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "domain":{ + "$ref":"#/definitions/DdsDomain" + }, + "status":{ + "$ref":"#/definitions/MonitorProducerConfig" + }, + "topics":{ + "$ref":"#/definitions/MonitorProducerConfig" + } + }, + "title": "MonitorConfig" + }, + "MonitorProducerConfig":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "enable":{ + "type":"boolean" + }, + "domain":{ + "$ref":"#/definitions/DdsDomain" + }, + "period":{ + "type":"number", + "exclusiveMinimum": 0 + }, + "topic-name":{ + "type":"string" + } + }, + "required":[ + "enable" + ], + "title": "MonitorProducerConfig" + }, "TopicFilter":{ "type":"object", "additionalProperties":false, @@ -60,8 +263,11 @@ "type":{ "type":"string" }, - "keyed":{ - "type":"boolean" + "qos":{ + "$ref":"#/definitions/QOS" + }, + "filter":{ + "type":"string" } }, "required":[ @@ -78,19 +284,83 @@ }, "type":{ "type":"string" + } + }, + "required":[ + "name", + "type" + ], + "title":"TopicBuiltins" + }, + "RouteConfig":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "src":{ + "type":"string" }, - "keyed":{ - "type":"boolean" + "dst":{ + "type":"array", + "items":{ + "type":"string" + } + } + }, + "required":[ + "src" + ], + "title":"RouteConfig" + }, + "TopicRouteConfig":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "name":{ + "type":"string" }, - "reliable":{ - "type":"boolean" + "type":{ + "type":"string" + }, + "routes":{ + "type":"array", + "items":{ + "$ref":"#/definitions/RouteConfig" + } } }, "required":[ "name", "type" ], - "title":"TopicBuiltins" + "title":"TopicRouteConfig" + }, + "ManualTopic":{ + "type":"object", + "additionalProperties":false, + "properties":{ + "name":{ + "type":"string" + }, + "type":{ + "type":"string" + }, + "qos":{ + "$ref":"#/definitions/QOS" + }, + "filter":{ + "type":"string" + }, + "participants":{ + "type":"array", + "items":{ + "type":"string" + } + } + }, + "required":[ + "name" + ], + "title":"ManualTopic" }, "Participant":{ "type":"object", @@ -102,25 +372,24 @@ "kind":{ "type":"string", "enum":[ - "void", "echo", - "dummy", "local", "simple", + "wan", + "router", + "initial-peers", "discovery-server", "ds", "local-ds", "local-discovery-server", "wan-ds", "wan-discovery-server", - "wan", - "router" + "xml", + "XML" ] }, "domain":{ - "type":"integer", - "minimum":0, - "maximum":230 + "$ref":"#/definitions/DdsDomain" }, "repeater":{ "type":"boolean" @@ -130,24 +399,17 @@ }, "listening-addresses":{ "type":"array", + "minItems":1, "items":{ "$ref":"#/definitions/Address" - }, - "minItems": 1 + } }, "connection-addresses":{ "type":"array", + "minItems":1, "items":{ - "anyOf":[ - { - "$ref":"#/definitions/DsConnectionAddress" - }, - { - "$ref":"#/definitions/Address" - } - ] - }, - "minItems": 1 + "$ref":"#/definitions/Address" + } }, "tls":{ "$ref":"#/definitions/TLS" @@ -160,6 +422,39 @@ }, "verbose":{ "type":"boolean" + }, + "whitelist-interfaces":{ + "type":"array", + "items":{ + "type":"string" + } + }, + "ros2-easy-mode":{ + "$ref":"#/definitions/IPv4" + }, + "transport":{ + "type":"string", + "enum":[ + "builtin", + "udp", + "shm" + ] + }, + "ignore-participant-flags":{ + "type":"string", + "enum":[ + "no_filter", + "filter_different_host", + "filter_different_process", + "filter_same_process", + "filter_different_and_same_process" + ] + }, + "qos":{ + "$ref":"#/definitions/QOS" + }, + "profile":{ + "type":"string" } }, "required":[ @@ -173,8 +468,7 @@ "kind":{ "type":"string", "enum":[ - "void", - "dummy" + "echo" ] } } @@ -211,63 +505,32 @@ } }, - "discovery":{ + "whitelist-interfaces":{ "not":{ } }, - "data":{ + "ros2-easy-mode":{ "not":{ } }, - "verbose":{ - "not":{ - - } - } - } - } - }, - { - "if":{ - "properties":{ - "kind":{ - "type":"string", - "enum":[ - "echo" - ] - } - } - }, - "then":{ - "properties":{ - "domain":{ - "not":{ - - } - }, - "discovery-server-guid":{ - "not":{ - - } - }, - "listening-addresses":{ + "transport":{ "not":{ } }, - "connection-addresses":{ + "ignore-participant-flags":{ "not":{ } }, - "tls":{ + "qos":{ "not":{ } }, - "repeater":{ + "profile":{ "not":{ } @@ -329,6 +592,11 @@ "verbose":{ "not":{ + } + }, + "profile":{ + "not":{ + } } } @@ -361,6 +629,11 @@ } }, + "repeater":{ + "not":{ + + } + }, "discovery":{ "not":{ @@ -374,15 +647,15 @@ "verbose":{ "not":{ + } + }, + "profile":{ + "not":{ + } } } }, - { - "required":[ - "discovery-server-guid" - ] - }, { "anyOf":[ { @@ -407,7 +680,8 @@ "type":"string", "enum":[ "wan", - "router" + "router", + "initial-peers" ] } } @@ -434,6 +708,11 @@ "verbose":{ "not":{ + } + }, + "profile":{ + "not":{ + } } } @@ -454,6 +733,97 @@ } ] } + }, + { + "if":{ + "properties":{ + "kind":{ + "type":"string", + "enum":[ + "xml", + "XML" + ] + } + } + }, + "then":{ + "allOf":[ + { + "properties":{ + "domain":{ + "not":{ + + } + }, + "discovery-server-guid":{ + "not":{ + + } + }, + "listening-addresses":{ + "not":{ + + } + }, + "connection-addresses":{ + "not":{ + + } + }, + "tls":{ + "not":{ + + } + }, + "discovery":{ + "not":{ + + } + }, + "data":{ + "not":{ + + } + }, + "verbose":{ + "not":{ + + } + }, + "whitelist-interfaces":{ + "not":{ + + } + }, + "ros2-easy-mode":{ + "not":{ + + } + }, + "transport":{ + "not":{ + + } + }, + "ignore-participant-flags":{ + "not":{ + + } + }, + "qos":{ + "not":{ + + } + } + } + }, + { + "required":[ + "profile" + ] + } + ] + } } ], "title":"Participant" @@ -466,7 +836,8 @@ "type":"string" }, "id":{ - "type":"integer" + "type":"integer", + "minimum": 0 }, "ros-discovery-server":{ "type":"boolean" @@ -486,26 +857,6 @@ ], "title":"DiscoveryServerGUID" }, - "DsConnectionAddress":{ - "type":"object", - "additionalProperties":false, - "properties":{ - "discovery-server-guid":{ - "$ref":"#/definitions/DiscoveryServerGUID" - }, - "addresses":{ - "type":"array", - "items":{ - "$ref":"#/definitions/Address" - } - } - }, - "required":[ - "addresses", - "discovery-server-guid" - ], - "title":"DsConnectionAddress" - }, "TLS":{ "type":"object", "additionalProperties":false, @@ -614,15 +965,7 @@ "additionalProperties":false, "properties":{ "ip":{ - "type":"string", - "anyOf":[ - { - "format":"v4" - }, - { - "format":"v6" - } - ] + "type":"string" }, "domain":{ "type":"string" @@ -667,6 +1010,71 @@ } ] }, + { + "if": { + "not": { + "required": ["ip-version"] + } + }, + "then": { + "properties": { + "ip": { + "anyOf":[ + { + "format":"v4" + }, + { + "format":"v6" + } + ] + } + } + } + }, + { + "if":{ + "properties":{ + "ip-version":{ + "type":"string", + "enum":[ + "v4" + ] + } + }, + "required":[ + "ip-version" + ] + }, + "then":{ + "properties":{ + "ip":{ + "format": "v4" + } + } + } + }, + { + "if":{ + "properties":{ + "ip-version":{ + "type":"string", + "enum":[ + "v6" + ] + } + }, + "required":[ + "ip-version" + ] + }, + "then":{ + "properties":{ + "ip":{ + "format": "v6" + } + } + } + }, { "required":[ "port" @@ -674,6 +1082,17 @@ } ], "title":"Address" + }, + "IPv4":{ + "type":"string", + "format":"v4", + "title":"IPv4" + }, + "DdsDomain":{ + "type":"integer", + "minimum": 0, + "maximum": 232, + "title":"DdsDomain" } } -} \ No newline at end of file +} diff --git a/resources/configurations/examples/ros_discovery_client.yaml b/resources/configurations/examples/ros_discovery_client.yaml index 5df28d604..f50ea6fd4 100644 --- a/resources/configurations/examples/ros_discovery_client.yaml +++ b/resources/configurations/examples/ros_discovery_client.yaml @@ -28,7 +28,6 @@ participants: - name: ClientROS2 # 5 kind: local-discovery-server # 6 - connection-addresses: # 7 - domain: localhost # 8 port: 11888 # 9 diff --git a/resources/configurations/examples/wan_client.yaml b/resources/configurations/examples/wan_client.yaml index 4dd908b8e..4820e05e8 100644 --- a/resources/configurations/examples/wan_client.yaml +++ b/resources/configurations/examples/wan_client.yaml @@ -26,7 +26,7 @@ participants: # INITIAL PEERS CLIENT # This participant will subscribe to topics in allowlist using Initial Peers Discovery protocol connecting to remote. - - name: WanParticipant # 6 + - name: WanClient # 6 kind: wan # 7 connection-addresses: # 8 - ip: 1.1.1.1 @@ -59,7 +59,7 @@ participants: # 5: SimpleParticipant will use DDS Domain ID <1>. -# 6: New Participant with name . +# 6: New Participant with name . # 7: Kind of WANClient: . # InitialPeers discovery to discover and communicate with another Initial Peers participant. diff --git a/resources/configurations/examples/wan_ds_client.yaml b/resources/configurations/examples/wan_ds_client.yaml index 49bb88bb4..2873f68e7 100644 --- a/resources/configurations/examples/wan_ds_client.yaml +++ b/resources/configurations/examples/wan_ds_client.yaml @@ -35,6 +35,7 @@ participants: - ip: 2.2.2.2 # 11 port: 11670 # 12 transport: udp # 13 + ################################## # CONFIGURATION DESCRIPTION @@ -65,6 +66,19 @@ participants: # 8: Add the addresses where to reach the remote DDS Routers that will connect to. # Add as many connection-addresses as needed. -# 9: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11777 over TCP transport. +# 9: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11666 over UDP transport (default). # This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. # Add every other address where trying to reach this same remote WAN Discovery Server. + +# 10: Add the interfaces where this Participant will listen in WAN. +# This is only needed if Remote WAN Server is using only UDP. +# Add as many listening-addresses as needed. + +# 11: Listen in public IP (2.2.2.2) for remote traffic. +# This IP must be set to the public IP of the host where this DDS Router will run. + +# 12: Listening port is 11670. +# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network +# router to this host to the same port. + +# 13: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/resources/configurations/examples/wan_ds_server.yaml b/resources/configurations/examples/wan_ds_server.yaml index 4287599d1..02876cf52 100644 --- a/resources/configurations/examples/wan_ds_server.yaml +++ b/resources/configurations/examples/wan_ds_server.yaml @@ -39,8 +39,8 @@ participants: # This configuration example configures a DDS Router to listen to every message published in domain 0 in topics # HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages # through a Discovery Server WAN Participant (configured as Server) to another Discovery Server WAN Participant. -# The other direction of communication is also possible; receive messages at the Discovery Server WAN Participant and locally -# publish them in domain 0. +# The other direction of communication is also possible; receive messages at the Discovery Server WAN Participant +# and locally publish them in domain 0. # Server specifies which DDS Router starts the communication with the other, and after communication has been # established, both routers behave in the same way. @@ -70,8 +70,4 @@ participants: # Remember that if the host is under a NAT, this port is the one that the host will open, but not the one # used as public in the router. -# 11: External port is 11777. -# This port is used in case the host is under a NAT. This is the public port accessible from any external point -# in the network, and should be forwarded from the network router to the "port" value. - -# 12: It uses TCP. UDP transport is used by default if not set. Could be set to "udp" or "tcp". +# 11: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/resources/configurations/examples/wan_server.yaml b/resources/configurations/examples/wan_server.yaml index 565f19061..6d163f2a7 100644 --- a/resources/configurations/examples/wan_server.yaml +++ b/resources/configurations/examples/wan_server.yaml @@ -26,12 +26,12 @@ participants: # WAN SERVER # This participant will subscribe to topics in allowlist using Initial Peers Discovery protocol awaiting connections. - - name: WanParticipant # 6 + - name: WanServer # 6 kind: wan # 7 - listening-addresses: - - ip: 1.1.1.1 # 8 - port: 11666 # 9 - transport: udp # 10 + listening-addresses: # 8 + - ip: 1.1.1.1 # 9 + port: 11666 # 10 + transport: udp # 11 ################################## # CONFIGURATION DESCRIPTION @@ -55,14 +55,17 @@ participants: # 5: SimpleParticipant will use DDS Domain ID <0>. -# 6: New Participant with name . +# 6: New Participant with name . # 7: Kind of WANClient: . # InitialPeers discovery to discover and communicate with another WAN DDS Router. -# 8: Listen in public IP (1.1.1.1) for remote traffic. +# 8: Add the interfaces where this Participant will listen in WAN. +# Add as many listening-addresses as needed. + +# 9: Listen in public IP (1.1.1.1) for remote traffic. # This IP must be set to the public IP of the host where this DDS Router will run. -# 9: Listening port is 11666. +# 10: Listening port is 11666. -# 10: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". +# 11: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/tools/ddsrouter_tool/test/application/configurations/complex_configuration.yaml b/tools/ddsrouter_tool/test/application/configurations/complex_configuration.yaml index 36a12d75d..c42e26ab8 100644 --- a/tools/ddsrouter_tool/test/application/configurations/complex_configuration.yaml +++ b/tools/ddsrouter_tool/test/application/configurations/complex_configuration.yaml @@ -75,9 +75,10 @@ participants: port: 11668 transport: tcp - ip: "0.0.0.0" + port: 11669 listening-addresses: - ip: "127.0.0.1" - port: 11669 + port: 11670 - name: XML-DDS kind: xml diff --git a/tools/ddsrouter_yaml_validator/.gitignore b/tools/ddsrouter_yaml_validator/.gitignore deleted file mode 100644 index f42e32aba..000000000 --- a/tools/ddsrouter_yaml_validator/.gitignore +++ /dev/null @@ -1,98 +0,0 @@ - -### C++ ### -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.app - -### Vim ### -# swap -[._]*.s[a-w][a-z] -[._]s[a-w][a-z] -# session -Session.vim -# temporary -.netrwhist -*~ -# auto-generated tag files -tags - -build/ -install/ -# Log is commented because some internal modules could be called like that -# log/ - -### Visual Studio ### -.vs - -### Visual Studio Code ### -.vscode - -### Documentation ### -docs/rst/_static/css/online_eprosima_rtd_theme.css - -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_yaml_validator.py b/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_yaml_validator.py deleted file mode 100644 index 9e2cadb99..000000000 --- a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_yaml_validator.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""DDS-Router YAML Validator tool.""" - -from ddsrouter_yaml_validator.parser import Parser -from ddsrouter_yaml_validator.validator import YamlValidator - - -def main(args=None): - """Validate a DDS-Router YAML configuration file.""" - parser = Parser() - args = parser.parse() - - validator = YamlValidator() - validator.validate(args.config_file, args.schema, args.recursive) - - -if __name__ == '__main__': - main() diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/full_example.yaml b/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/full_example.yaml deleted file mode 100644 index 11554456c..000000000 --- a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/full_example.yaml +++ /dev/null @@ -1,90 +0,0 @@ -version: v5.0 # Required - -threads: 32 # Optional - -allowlist: -- name: rt/chatter # Required - type: std_msgs::msg::dds_::String_ - keyed: true - -blocklist: -- name: rt/chatter # Required - type: std_msgs::msg::dds_::String_ - keyed: true - -builtin-topics: -- name: rt/chatter # Required - type: std_msgs::msg::dds_::String_ # Required - -- name: custom_topic # Required - type: custom_topic_type # Required - -topics: - - name: rt/chatter - qos: - keyed: true - - -participants: -- name: participant0 # Required - kind: echo # Required - -- name: participant1 # Required - kind: simple # Required - domain: 1 - -- name: participant2 - kind: discovery-server - discovery-server-guid: # Required - guid: 01.0f.00.00.00.00.00.00.00.00.ca.fe # Required guid or id - id: 0 # Required guid or id - ros-discovery-server: true - listening-addresses: # Required listening-addresses or connection-addresses - - ip: 127.0.0.1 # Required ip or domain - domain: localhost # Required ip or domain - port: 11667 # Required - transport: udp - ip-version: ipv4 - connection-addresses: # Required listening-addresses or connection-addresses - - discovery-server-guid: # Required - guid: 01.0f.00.00.00.00.00.00.00.00.ca.fe # Required guid or id - id: 0 # Required guid or id - ros-discovery-server: true - addresses: # Required - - ip: 127.0.0.1 # Required ip or domain - domain: localhost # Required ip or domain - port: 11667 # Required - transport: udp - ip-version: ipv4 - tls: - ca: ca.crt # Required - password: ddsrouterpass # If "password" present, "private_key" and "cert" required - private_key: ddsrouter.key # If "private_key" present, "password" and "cert" required - cert: ddsrouter.crt # If "cert" present, "password" and "private_key" required - dh_params: dh_params.pem - -- name: participant3 - kind: wan - discovery-server-guid: # Required - guid: 01.0f.00.00.00.00.00.00.00.00.ca.fe # Required guid or id - id: 0 # Required guid or id - ros-discovery-server: true - listening-addresses: # Required listening-addresses or connection-addresses - - ip: ::1 # Required ip or domain - domain: localhost # Required ip or domain - port: 11667 - transport: tcp - ip-version: ipv6 - connection-addresses: # Required listening-addresses or connection-addresses - - discovery-server-guid: - guid: 01.0f.00.00.00.00.00.00.00.00.ca.fe # Required guid or id - id: 0 # Required guid or id - ros-discovery-server: true - addresses: - - ip: 127.0.0.1 # Required ip or domain - domain: localhost # Required ip or domain - port: 11667 - transport: tcp - ip-version: ipv4 - tls: - ca: ca.crt # Required diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/parser.py b/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/parser.py deleted file mode 100644 index 2a7c85063..000000000 --- a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/parser.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Argument parser for DDS-Router YAML Validator tool.""" - -import argparse -import os - - -class Parser: - """DDS-Router YAML Validator argument parser.""" - - def parse(self): - """Parse configuration and schema path arguments.""" - parser = argparse.ArgumentParser( - description='Validate DDS-Router configuration file.' - ) - parser.add_argument( - '-c', - '--config-file', - required=True, - help='YAML file or directory with files used to configure' - 'DDS-Router', - ) - parser.add_argument( - '-r', - '--recursive', - action='store_true', - default=False, - help='Whether to perform recursive search when --config-file' - ' refers to a directory (default: false)', - ) - parser.add_argument( - '-s', - '--schema', - default=os.path.join( - os.environ['COLCON_PREFIX_PATH'], - 'ddsrouter_yaml_validator/share/ddsrouter_yaml_validator/' - 'ddsrouter_config_schema.json', - ), - help='JSON schema used to perform validation', - ) - return parser.parse_args() diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/validator.py b/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/validator.py deleted file mode 100644 index 201b702e1..000000000 --- a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/validator.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""DDS-Router YAML Validator class container.""" - -import json -import os - -import jsonschema - -import yaml - - -class YamlValidator: - """ - Used to validate DDS-Router YAML configuration files against a schema. - - It exposes a static method for this purpose. - DDS-Router configurations are YAML files, and the schema is in JSON format. - """ - - def validate(self, config_path, schema_path, recursive=True, logout=True): - """Validate configuration file or files under a directory.""" - if not self.__is_json(schema_path): - print( - 'The given schema {} is not a JSON file.'.format( - os.path.basename(schema_path) - ) - ) - return - - if os.path.isdir(config_path): - ret = True - visited_dirs = [] - for root, dirs, files in os.walk(config_path): - print(f'Scanning directory {root}') - if root not in visited_dirs: - visited_dirs.append(root) - for f in files: - if self.__is_yaml(f): - ret = ret and self.__validate_config_file( - os.path.join(root, f), schema_path, logout) - if not recursive: - break - return ret - else: - if self.__is_yaml(config_path): - return self.__validate_config_file( - config_path, schema_path, logout) - else: - print( - 'The given config file {} is not a YAML file.'.format( - os.path.basename(config_path))) - - def __validate_config_file(self, config_file_path, schema_path, - logout=True): - """Validate DDS-Router configuration file.""" - with open(schema_path) as json_file: - schema = json.load(json_file) - with open(config_file_path) as yaml_file: - config_yaml = yaml.safe_load(yaml_file) - config_json = json.loads(json.dumps(config_yaml)) - try: - jsonschema.validate(config_json, schema) - except jsonschema.exceptions.ValidationError as exception: - if logout: - print(exception) - return False - - if logout: - print(os.path.basename(config_file_path), - 'is a valid DDS-Router configuration file.') - return True - - def __is_json(self, file): - """ - Check if a file is a JSON file. - - :param file: The input file - :return: True if the file is an JSON file, False if not. - """ - return os.path.splitext(str(file))[-1] == '.json' - - def __is_yaml(self, file): - """ - Check if a file is a YAML file. - - :param file: The input file - :return: True if the file is an YAML file, False if not. - """ - ext = os.path.splitext(str(file))[-1] - return ext == '.yaml' or ext == '.yml' diff --git a/tools/ddsrouter_yaml_validator/package.xml b/tools/ddsrouter_yaml_validator/package.xml deleted file mode 100644 index 0b92759fe..000000000 --- a/tools/ddsrouter_yaml_validator/package.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - ddsrouter_yaml_validator - 3.5.1 - Tool used for validating DDS-Router configuration files - Raúl Sánchez-Mateos - Javier París - Juan López - Apache License, Version 2.0 - - python3-pytest - - - ament_python - - diff --git a/tools/ddsrouter_yaml_validator/resource/ddsrouter_yaml_validator b/tools/ddsrouter_yaml_validator/resource/ddsrouter_yaml_validator deleted file mode 100644 index e69de29bb..000000000 diff --git a/tools/ddsrouter_yaml_validator/setup.cfg b/tools/ddsrouter_yaml_validator/setup.cfg deleted file mode 100644 index 3c1f99b9e..000000000 --- a/tools/ddsrouter_yaml_validator/setup.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[develop] -script_dir=$base/bin -[install] -install_scripts=$base/bin diff --git a/tools/ddsrouter_yaml_validator/setup.py b/tools/ddsrouter_yaml_validator/setup.py deleted file mode 100644 index cde18500e..000000000 --- a/tools/ddsrouter_yaml_validator/setup.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Setup file to install ddsrouter_yaml_validator module.""" -from setuptools import setup - - -package_name = 'ddsrouter_yaml_validator' - -setup( - name=package_name, - version='3.5.1', - packages=[package_name], - data_files=[ - ('share/ament_index/resource_index/packages', - ['resource/' + package_name]), - ('share/' + package_name, ['package.xml']), - ('share/' + package_name, [package_name + '/ddsrouter_config_schema.json']), - ('share/' + package_name, [package_name + '/full_example.yaml']) - ], - install_requires=['setuptools'], - zip_safe=True, - maintainer='eprosima', - maintainer_email='juanlopez@eprosima.com', - description='Tool used for validating DDS-Router configuration files', - license='Apache License, Version 2.0', - tests_require=['pytest'], - test_suite='tests', - entry_points={ - 'console_scripts': [ - 'ddsrouter_yaml_validator = ddsrouter_yaml_validator.ddsrouter_yaml_validator:main', - ], - }, -) diff --git a/tools/ddsrouter_yaml_validator/tests/__init__.py b/tools/ddsrouter_yaml_validator/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py b/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py deleted file mode 100644 index 9210ccac7..000000000 --- a/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""DDS-Router YAML Validator tests.""" - -import os - -from ddsrouter_yaml_validator.validator import YamlValidator - - -# Move to project root level -os.chdir(os.path.dirname(os.path.abspath(__file__)) + '/../../..') - -SCHEMA_PATH = 'tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/' \ - 'ddsrouter_config_schema.json' - -VALID_CONFIGURATION_FILES = [ - 'resources/configurations/examples', - 'docs/resources/getting_started'] - -INVALID_CONFIGURATION_FILES = [ - 'tools/ddsrouter_yaml_validator/tests/invalid_configuration_files'] - - -def test_valid_yamls(): - """Assert given configuration files are valid.""" - validator = YamlValidator() - for valid_files_dir in VALID_CONFIGURATION_FILES: - for root, dirs, files in os.walk(valid_files_dir): - for file in files: - file_path = os.path.join(root, file) - assert validator.validate(file_path, SCHEMA_PATH, logout=False), 'Test error: ' + file_path - - -def test_invalid_yamls(): - """Assert given configuration files are invalid.""" - validator = YamlValidator() - for invalid_files_dir in INVALID_CONFIGURATION_FILES: - assert not validator.validate( - invalid_files_dir, SCHEMA_PATH, logout=False), 'Negative test error: ' + invalid_files_dir