Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/references/docker_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@
},
"Proxy Host": {
"name": "Proxy Host",
"description": "Proxy host name or IP. Use https:// prefix for HTTPS proxy. DEPRECATED, please use Proxy Configuration Service instead.",
"description": "Proxy host name or IP. DEPRECATED, please use Proxy Configuration Service instead.",
"validator": "VALID",
"required": "false",
"sensitive": "false",
Expand Down Expand Up @@ -853,7 +853,7 @@
},
"Proxy Host": {
"name": "Proxy Host",
"description": "Proxy host name or IP. Use https:// prefix for HTTPS proxy. DEPRECATED, please use Proxy Configuration Service instead.",
"description": "Proxy host name or IP. DEPRECATED, please use Proxy Configuration Service instead.",
"validator": "VALID",
"required": "false",
"sensitive": "false",
Expand Down Expand Up @@ -1226,7 +1226,7 @@
},
"Proxy Host": {
"name": "Proxy Host",
"description": "Proxy host name or IP. Use https:// prefix for HTTPS proxy. DEPRECATED, please use Proxy Configuration Service instead.",
"description": "Proxy host name or IP. DEPRECATED, please use Proxy Configuration Service instead.",
"validator": "VALID",
"required": "false",
"sensitive": "false",
Expand Down Expand Up @@ -1615,7 +1615,7 @@
},
"Proxy Host": {
"name": "Proxy Host",
"description": "Proxy host name or IP. Use https:// prefix for HTTPS proxy. DEPRECATED, please use Proxy Configuration Service instead.",
"description": "Proxy host name or IP. DEPRECATED, please use Proxy Configuration Service instead.",
"validator": "VALID",
"required": "false",
"sensitive": "false",
Expand Down Expand Up @@ -2046,7 +2046,7 @@
},
"Proxy Host": {
"name": "Proxy Host",
"description": "Proxy host name or IP. Use https:// prefix for HTTPS proxy. DEPRECATED, please use Proxy Configuration Service instead.",
"description": "Proxy host name or IP. DEPRECATED, please use Proxy Configuration Service instead.",
"validator": "VALID",
"required": "false",
"sensitive": "false",
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,10 @@ jobs:
sudo rm -rf /opt/ghc
sudo rm -rf "/usr/local/share/boost"
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- id: dry_run
name: Behave dry run
working-directory: ./build
run: make docker-verify-modular-dry-run
- id: test
name: Docker Verify
working-directory: ./build
Expand Down Expand Up @@ -622,6 +626,10 @@ jobs:
run: |
sudo apt update
sudo apt install -y python3-virtualenv
- id: dry_run
name: Behave dry run
working-directory: ./build
run: ../docker/DryRunBehaveTests.sh ../minifi_rust
- id: test
name: Docker Verify
working-directory: ./minifi_rust
Expand Down
8 changes: 4 additions & 4 deletions PROCESSORS.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions cmake/DockerConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ add_custom_target(
docker-verify-modular
COMMAND ${CMAKE_SOURCE_DIR}/docker/RunBehaveTests.sh ${PROJECT_VERSION_STR} ${ENABLED_TAGS} --tags_to_exclude=${DISABLED_TAGS} --parallel_processes=${DOCKER_VERIFY_THREADS})

add_custom_target(
docker-verify-modular-dry-run
COMMAND ${CMAKE_SOURCE_DIR}/docker/DryRunBehaveTests.sh --tags_to_run=${ENABLED_TAGS} --tags_to_exclude=${DISABLED_TAGS} ${CMAKE_SOURCE_DIR}/extensions ${CMAKE_SOURCE_DIR}/minifi_rust/extensions)

function(CREATE_DOCKER_TARGET_FROM_ROCKY_PACKAGE BASE_IMAGE TAG_PREFIX INSTALL_PACKAGE_CMD)
add_custom_target(
${TAG_PREFIX}_from_rocky_package
Expand Down
129 changes: 129 additions & 0 deletions docker/DryRunBehaveTests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/bin/bash

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

set -e

print_help()
{
printf '%s\n' "Dry runs the behave feature directories found in the provided directories"
printf '%s\n' "to catch environment.py and step module loading errors, which are silently skipped by behavex"
printf 'Usage: %s [--tags_to_run=<arg>] [--tags_to_exclude=<arg>] [-h|--help] <search_dir> ...\n' "$0"
printf '\t%s\n' "<search_dir>: directory to search for feature files recursively"
printf '\t%s\n' "--tags_to_run: optional comma-separated list of tags to include, only the feature directories having features with any of these tags are checked (default: all)"
printf '\t%s\n' "--tags_to_exclude: optional comma-separated list of tags that should be skipped (default: none)"
printf '\t%s\n' "-h, --help: Prints help"
}

tags_to_run=
tags_to_exclude=
search_dirs=()
for arg in "$@"; do
case "${arg}" in
--tags_to_run=*)
tags_to_run="${arg##--tags_to_run=}"
;;
--tags_to_exclude=*)
tags_to_exclude="${arg##--tags_to_exclude=}"
;;
-h|--help)
print_help
exit 0
;;
*)
search_dirs+=("${arg}")
;;
esac
done

if [ "${#search_dirs[@]}" -eq 0 ]; then
print_help >&2
exit 1
fi

root_dir="$( cd "${0%/*}/.." && pwd )"

# Create virtual environment for testing
if [[ ! -d ./behave_venv ]]; then
echo "Creating virtual environment in ./behave_venv" 1>&2
virtualenv --python=python3 ./behave_venv
fi

echo "Activating virtual environment..." 1>&2
# shellcheck disable=SC1091
. ./behave_venv/bin/activate
pip install -e "${root_dir}/behave_framework"

TAG_OPTS=()
if [ -n "${tags_to_run}" ]; then
TAG_OPTS+=(-t "${tags_to_run}")
fi
IFS=',' read -ra excluded_tags <<< "${tags_to_exclude}"
for tag in "${excluded_tags[@]}"; do
TAG_OPTS+=(-t "~${tag}")
done

FEATURE_FILES=()
while IFS= read -r -d '' file; do
FEATURE_FILES+=("${file}")
done < <(find "${search_dirs[@]}" -name .venv -prune -o -type f -name '*.feature' -print0)

if [ "${#FEATURE_FILES[@]}" -eq 0 ]; then
echo "No feature files found in: ${search_dirs[*]}" >&2
exit 1
fi

# Scenario Outlines without example rows are silently dropped by behave
python3 -I - "${FEATURE_FILES[@]}" <<'EOF'
import sys
from behave.model import ScenarioOutline
from behave.parser import parse_file

empty_outlines = []
for feature_file in sys.argv[1:]:
for scenario in parse_file(feature_file).walk_scenarios(with_outlines=True):
if isinstance(scenario, ScenarioOutline) and not any(examples.table and examples.table.rows for examples in scenario.examples):
empty_outlines.append(f"{feature_file}:{scenario.line}: {scenario.name}")

if empty_outlines:
print("Scenario Outlines without examples found, use Scenario instead:", file=sys.stderr)
print("\n".join(f" {outline}" for outline in empty_outlines), file=sys.stderr)
sys.exit(1)
EOF

FEATURE_DIRS=()
while IFS= read -r dir; do
FEATURE_DIRS+=("${dir}")
done < <(
if [ -n "${tags_to_run}" ]; then
grep -lE "@(${tags_to_run//,/|})([[:space:]]|$)" "${FEATURE_FILES[@]}"
else
printf '%s\n' "${FEATURE_FILES[@]}"
fi | sed 's|/[^/]*$||' | sort -u)

failed_dirs=()
for dir in "${FEATURE_DIRS[@]}"; do
echo "Dry run of ${dir}" 1>&2
behave --dry-run --no-summary --format null "${TAG_OPTS[@]}" "${dir}" || failed_dirs+=("${dir}")
done

if [ "${#failed_dirs[@]}" -gt 0 ]; then
echo "Behave dry run failed, the following feature directories could not be loaded:" >&2
printf ' %s\n' "${failed_dirs[@]}" >&2
exit 1
fi

echo "Behave dry run succeeded for ${#FEATURE_DIRS[@]} feature directories" 1>&2
8 changes: 7 additions & 1 deletion extensions/aws/processors/AwsProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,15 @@ void AwsProcessor::onSchedule(core::ProcessContext& context, core::ProcessSessio

auto proxy = getProxy(context);
if (proxy.proxy_type != minifi::controllers::ProxyType::DIRECT) {
if (minifi::utils::string::startsWith(proxy.proxy_host, "https://")) {
static constexpr std::string_view HTTPS_PREFIX = "https://";
if (minifi::utils::string::startsWith(proxy.proxy_host, HTTPS_PREFIX, false)) {
throw Exception(PROCESS_SCHEDULE_EXCEPTION, "HTTPS proxy is not supported");
}
// the AWS CRT client expects a plain host name without a scheme
static constexpr std::string_view HTTP_PREFIX = "http://";
if (minifi::utils::string::startsWith(proxy.proxy_host, HTTP_PREFIX, false)) {
proxy.proxy_host.erase(0, HTTP_PREFIX.size());
}
client_config_.proxyScheme = Aws::Http::Scheme::HTTP;
client_config_.proxyHost = proxy.proxy_host;
client_config_.proxyPort = proxy.proxy_port;
Expand Down
2 changes: 1 addition & 1 deletion extensions/aws/processors/AwsProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class AwsProcessor : public core::ProcessorImpl { // NOLINT(cppcoreguidelines-s
.withValidator(core::StandardPropertyValidators::NON_BLANK_VALIDATOR)
.build();
EXTENSIONAPI static constexpr auto ProxyHost = core::PropertyDefinitionBuilder<>::createProperty("Proxy Host")
.withDescription("Proxy host name or IP. Use https:// prefix for HTTPS proxy. DEPRECATED, please use Proxy Configuration Service instead.")
.withDescription("Proxy host name or IP. DEPRECATED, please use Proxy Configuration Service instead.")
.build();
EXTENSIONAPI static constexpr auto ProxyPort = core::PropertyDefinitionBuilder<>::createProperty("Proxy Port")
.withDescription("The port number of the proxy host. DEPRECATED, please use Proxy Configuration Service instead.")
Expand Down
15 changes: 14 additions & 1 deletion extensions/aws/tests/PutS3ObjectTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "S3TestsFixture.h"
#include "processors/PutS3Object.h"
#include "unit/TestUtils.h"
#include "catch2/generators/catch_generators.hpp"

namespace {

Expand Down Expand Up @@ -210,9 +211,21 @@ TEST_CASE_METHOD(PutS3ObjectTestsFixture, "Test proxy setting", "[awsS3Proxy]")
checkProxySettings();
}

TEST_CASE_METHOD(PutS3ObjectTestsFixture, "HTTP scheme is stripped from the proxy host", "[awsS3Proxy]") {
const auto proxy_host = GENERATE("host", "http://host", "HTTP://host");
setRequiredProperties();
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Host", proxy_host));
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Port", "1234"));
test_controller.runSession(plan);
CHECK(mock_s3_request_sender_ptr->getClientConfig().proxyScheme == Aws::Http::Scheme::HTTP);
CHECK(mock_s3_request_sender_ptr->getClientConfig().proxyHost == "host");
CHECK(mock_s3_request_sender_ptr->getClientConfig().proxyPort == 1234);
}

TEST_CASE_METHOD(PutS3ObjectTestsFixture, "HTTPS proxy is not supported", "[awsS3Proxy]") {
const auto proxy_host = GENERATE("https://host", "HTTPS://host");
setRequiredProperties();
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Host", "https://host"));
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Host", proxy_host));
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Port", "1234"));
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Username", "username"));
REQUIRE(this->plan->setProperty(this->s3_processor, "Proxy Password", "password"));
Expand Down
2 changes: 1 addition & 1 deletion extensions/aws/tests/S3TestsFixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class S3TestsFixture {

void checkProxySettings() {
REQUIRE(mock_s3_request_sender_ptr->getClientConfig().proxyScheme == Aws::Http::Scheme::HTTP);
REQUIRE(mock_s3_request_sender_ptr->getClientConfig().proxyHost == "http://host");
REQUIRE(mock_s3_request_sender_ptr->getClientConfig().proxyHost == "host");
REQUIRE(mock_s3_request_sender_ptr->getClientConfig().proxyPort == 1234);
REQUIRE(mock_s3_request_sender_ptr->getClientConfig().proxyUserName == "username");
REQUIRE(mock_s3_request_sender_ptr->getClientConfig().proxyPassword == "password");
Expand Down
Loading
Loading