Releases: code-lab-org/nost-tools
Releases · code-lab-org/nost-tools
NOS-T Tools v3.0.5
Added:
- Application Configuration Support: Added
configuration_parameterssupport for unmanagedApplicationclass:- Updated
ExecConfiginschemas.pyto includeapplicationsdictionary (similar tomanaged_applications) - Updated
ApplicationConfiginschemas.pyto includeconfiguration_parametersfield - Updated
get_app_specific_config()inconfiguration.pyto acceptapp_typeparameter ("applications" or "managed_applications") - Updated
Application._get_parameters_from_config()to retrieve app-specific config fromapplicationssection - Updated
ConnectionConfigto populateapplication_configurationfrom bothapplicationsandmanaged_applicationssections - Enables custom per-application configuration parameters in YAML
- Updated
- Resume Tolerance Configuration: Added global
resume_toleranceparameter toGeneralConfig:- Added
request_resume()method toApplicationclass that sendsResumeRequestmessages with optionalsim_resume_timeandtoleranceparameters - Removed duplicate
request_resume()fromManagedApplication- now inherits enhanced version fromApplication - Default tolerance of 12 hours can be configured globally in
execution.general.resume_tolerance - Can be overridden per-request by passing
toleranceparameter torequest_resume() - Example YAML structure:
execution: general: prefix: nost resume_tolerance: "12:00:00" # Global default for all applications
- Added
Full Changelog: v3.0.4...v3.0.5
NOS-T Tools v3.0.4
Added:
- Basic Authentication Mode: Added support for localhost/development connections without Keycloak authentication
- Allows
USERNAME+PASSWORDonly (no client credentials required) - Ideal for local RabbitMQ development without Keycloak infrastructure
- System now supports three distinct authentication modes instead of two
- Allows
- Enhanced Credentials Validation: Updated
validate_authentication_mode()inCredentialsschema to support three authentication modes:- Basic Auth (localhost):
USERNAME+PASSWORDonly - Keycloak Service Account:
CLIENT_ID+CLIENT_SECRET_KEYonly - Keycloak User Account:
USERNAME+PASSWORD+CLIENT_ID+CLIENT_SECRET_KEY
- Basic Auth (localhost):
- Comprehensive Three-Mode Testing: Added
test_basic_auth_mode_valid()test to verify localhost authentication works correctly - Optional Scenario Time and Tolerance for ResumeRequest: Added optional fields to
ResumeRequestParametersinschemas.py:sim_resume_time: Allows managed applications to specify target scenario time for resumetolerance: Time tolerance (timedelta) for matching scenario time to requested time- Both fields are optional and maintain backward compatibility (default to
None) - Uses
simResumeTimeandtolerancealiases for JSON serialization consistency
- Tolerance-Based Resume Command Logic: Added
_handle_resume_request()method inmanager.pyto handle tolerance-based resume requests:- Runs in a separate thread to avoid blocking message callbacks
- Default tolerance of 12 hours can be specified by managed applications
Changed:
- Credentials Validator (
schemas.py): Enhanced validation logic to recognize basic authentication as a valid mode alongside Keycloak authentication modes - Test Suite (
tests/test_credentials.py):- Renamed
test_user_account_mode_valid()totest_keycloak_user_account_mode_valid()for clarity - Updated test assertions to match new error messages
- Now testing 8 scenarios (was 7) including basic auth mode
- Renamed
- Error Messages: Updated validation error messages to include all three authentication modes for better troubleshooting
- Resume Request Handling (
manager.py): Modifiedon_resume_request()to delegate to_handle_resume_request()for tolerance-based handling:- If
toleranceis NOT provided:ResumeCommandis sent immediately (regardless ofsim_resume_time) - If
toleranceIS provided:- Both
toleranceandsim_resume_timeprovided: Checks if current scenario time is within tolerance of requested time- Within tolerance:
ResumeCommandis sent immediately - Outside tolerance: Request is ignored with informative log message showing time difference
- Within tolerance:
- Only
toleranceprovided (nosim_resume_time):ResumeCommandis sent immediately
- Both
- This tolerance-based approach allows managed applications to send multiple
ResumeRequestmessages with the Manager only acting when scenario time is within the specified tolerance window
- If
- Exchange Declaration (
application.py): Movedestablish_exchange()method fromManagerclass to baseApplicationclass:- All applications (unmanaged Application, ManagedApplication, and Manager) now automatically declare the exchange when channel opens
- Fixes "NOT_FOUND - no exchange" errors when unmanaged applications try to publish messages
- Exchange is declared in
on_channel_open()callback, ensuring it exists before any message operations - Eliminates requirement for Manager to run first before other applications can send messages
- Freeze Request Logging (
manager.py): Fixed misleading log message in_handle_freeze_request():- "Indefinite freeze requested - manual resume required" now logs before freeze starts (not after)
- Added "Indefinite freeze has ended" log message after freeze completes
- BasicProperties Handling (
application.py): Fixed RabbitMQ protocol error "UNEXPECTED_FRAME - expected content header for class 60":- Added
_build_basic_properties()helper method that filters outNonevalues before creatingpika.BasicProperties - Updated
send_message()and_process_message_queue()to use the new helper - Prevents protocol errors when YAML configuration has undefined/None BasicProperties fields
- Resolves random connection drops with error code 505 (UNEXPECTED_FRAME)
- Added
Full Changelog: v3.0.3...v3.0.4
NOS-T Tools v3.0.3
Added:
- Service Account Authentication Support: Applications can now authenticate with Keycloak using service accounts (client credentials only) without requiring username and password. This is ideal for automated systems, scripts, and long-running processes.
- Dual Authentication Modes: The system now supports two Keycloak authentication modes:
- User Account: Requires
USERNAME,PASSWORD,CLIENT_ID, andCLIENT_SECRET_KEY - Service Account: Requires only
CLIENT_IDandCLIENT_SECRET_KEY
- User Account: Requires
- Intelligent OTP Detection: Added smart OTP/TOTP requirement detection in
new_access_token()method that:- Analyzes Keycloak error responses for OTP-related keywords (
otp,totp,two-factor,2fa,mfa) - Only prompts for OTP when Keycloak explicitly indicates it's required
- Prevents false OTP prompts when username/password are incorrect
- Provides clear, context-specific error messages for different failure scenarios
- Analyzes Keycloak error responses for OTP-related keywords (
- Programmatic OTP Support: Added optional
otpparameter tonew_access_token()method to support automation with OTP-enabled accounts - Credentials Validation: Added
validate_authentication_mode()validator inCredentialsschema that enforces valid credential combinations and provides clear error messages for invalid configurations - Comprehensive Test Suite: Added
tests/test_credentials.pywith 7 tests covering both authentication modes and validation scenarios - Documentation:
- Created
KEYCLOAK_AUTH_MODES.mdwith detailed guide on both authentication modes, setup instructions, and error handling - Created
OTP_IMPROVEMENTS.mddocumenting intelligent OTP handling improvements - Created
.env.exampletemplate showing both authentication modes - Created
.env.sos.examplespecific template for sos.yaml configuration
- Created
Changed:
- Credentials Schema (
schemas.py): Changed default values forusernameandpasswordfrom"admin"toNoneto make them optional for service account authentication - Environment Variable Loading (
configuration.py): Updatedload_environment_variables()method to support optional username/password when Keycloak authentication is enabled, allowing service account mode - Authentication Method (
application.py): Updatednew_access_token()method to:- Automatically detect authentication mode based on presence of username/password
- Use
grant_type="password"for user authentication - Use
grant_type=["client_credentials"]for service account authentication - Intelligently handle OTP requirements with proper error detection
- Log which authentication mode is being used for debugging
- Error Messages: Improved authentication error messages to clearly indicate:
- "Authentication failed. Please check your username and password" for wrong credentials
- "OTP/TOTP is required for this account" when OTP is needed
- "The provided OTP may be incorrect or expired" for wrong OTP
Full Changelog: v3.0.2...v3.0.3
NOS-T Tools v3.0.2
Updated:
- Removed
self._next_time = self._timefromresume()insimulator.py, which was causing a drift of approximately 1 second per simulated day. - Changed a log statement in
freeze()withinmanager.pyfrom log.info to log.debug to reduce verbosity. The affected line reports the remaining time during a freeze.
Full Changelog: v3.0.1...v3.0.2
NOS-T Tools v3.0.1
Updated:
- Removed the calculation of
target_resume_timefrom thefreeze()method inmanager.py.
A freeze event now persists until the resume time specified in theFreezeCommandmessage payload is reached. Previously, the resume time was calculated from the scenario time at which theFreezeRequestmessage was received by the manager (scenario time at message receipt + freeze duration), which could cause time drift. - Prevented a one-step early advance after RESUMING by ensuring the
_wait_for_tock()method insimulator.pyre-anchors epochs and waits until the next tick before advancing. - Updated the
on_manager_freeze()method inmanaged_application.pyto honorsimFreezeTimefrom aFreezeCommand, aligning to the requested scenario time (via wallclock mapping) before callingpause()so all apps freeze at the same scenario time.
Full Changelog: v3.0.0...v3.0.1
NOS-T Tools v3.0.0
Added:
- Added comprehensive freeze time tracking system and callbacks in
Managerclass inmanager.pyto properly account for dynamic, distributed freezes, resumes, and updates to scenario time:- Added
on_freeze_request()callback which freezes scenario time based on messages containing requests from managed applications, integrated this callback intostart_up()method - Added
_handle_freeze_request()that handles dynamic, distributed freeze requests - Added
freeze()that issues freeze command, integrated this into the_handle_freeze_request() - Added
on_resume_request()callback which resumes scenario time based on messages containing requests from managed applications, integrated this callback intostart_up()method - Added
on_update_request()callback which updates the time scale factor based on messages containing requests from managed applications, integrated this callback intostart_up()method - Added
update()that issues update command, integrated this into theon_update_request()method
- Added
- Added new methods to
ManagedApplicationclass inmanaged_application.pyto allow requests for a freeze in scenario time from theManagerclass inmanager.py- Added
request_freeze()method that sends a FreezeRequest message which is received by theManagerapplication, added an associatedon_manager_freeze()callback that responds to FreezeCommand messages fromManger - Added
request_resume()method that sends a ResumeRequest message which is received by theManagerapplication, added an associatedon_manager_resume()callback that responds to ResumeCommand messages fromManager - Added
request_update()method that sends a UpdateRequest message which is received by theManagerapplication, added an associatedon_manager_update()callback that responds to UpdateCommand messages fromManager
- Added
- Added new freeze-tracking capabilities to
Simulatorclass insimulator.py- Added reset of wallclock and simulation epochs when mode switches to Mode.EXECUTING in
_wait_for_tock()method
- Added reset of wallclock and simulation epochs when mode switches to Mode.EXECUTING in
- Added the following classes to
schemas.py:FreezeTaskingParameters,FreezeCommand,ResumeTaskingParameters,ResumeCommand,FreezeRequestParameters,FreezeRequest,ResumeRequestParameters,ResumeRequest,UpdateRequestParameters,UpdateRequest
Updated:
- Removed code related to scheduled time scale updates in
_execute_test_plan_impl()ofManagerapplication. Scheduled time scale factor updates, defined in the YAML configuration file, are no longer supported. They must now be requested by aManagedApplicationand processed by theManagerwho maintains control of sending theFreezeCommandas defined inschemas.py - Removed
TimeScaleUpdateclass inmanager.py - Removed
TimeScaleUpdateSchemaandFreezeSchemaclasses inschemas.py - Removed
time_scale_updatesandfreezesfields fromManagerConfigclass inschemas.py - Prevent re-entrant execution in
Simulator.execute()by adding an explicit mode guard; now raises a clearRuntimeErrorwhen called outsideUNDEFINED,INITIALIZED, orTERMINATEDmodes:Cannot execute: simulator is {self._mode}. Wait for TERMINATED or terminate the current run. - Removed
WallclockOffsetPropertiesclass andwallclock_offset_propertiessection fromRuntimeConfiginschemas.pyandconfiguration.py. - Added
wallclock_offset_refresh_intervalandntp_hosttoGeneralConfigclass inschemas.py - Updated FireSat test suite to show examples of time scale updates and scenario time freezes.
Full Changelog: v2.4.0...v3.0.0
NOS-T Tools v2.4.0
Added:
- Introduced the
configure_file_logging()method in the baseApplicationclass, automatically invoked during thestart_up()process. - Added a
LoggingConfigPydantic model to encapsulate configuration parameters for theconfigure_file_logging()method.
Updated:
- Changed the default value of
token_refresh_intervalin theKeycloakConfigPydantic class from 60 seconds (1 minute) to 240 seconds (4 minutes).
Full Changelog: v2.3.0...v2.4.0
NOS-T Tools v2.3.0
Added:
- Introduced a boolean
setup_signal_handlers(default=True) parameter for Application() class, which makesself._setup_signal_handlers()conditional. This prevents errors in nost-manager-backend.- Added
setup_signal_handlersargument (default=True) to__init__ofManagerandManagedApplicationclasses.
- Added
- Added
yaml_filesection toRuntimeConfigin bothschemas.pyandconfiguration.py. This attribute holds the path to YAML configuration file if provided; otherwise, it defaults toNone. - Introduced
_get_parameters_from_config()inApplication,Manager, andManagedApplicationto facilitate getting the application parameters from the YAML configuration or user-provided arguments based onself.config.rc.yaml_filebeing None or not. - Added
keycloak_authenticationargument to__init__()ofConnectionConfigclass (default=False). - Implemented
start_wallclock_refresh_thread()which periodically updates the wallclock offset. - Added
WallclockOffsetPropertiestoschemas.pythat containswallclock_offset_refresh_intervalandntp_hostfields used instart_wallclock_refresh_thread() - Implemented
is_scenario_time_stepinManagerConfigclass, similar to that ofManagedApplicationConfig
Updated:
- Made
generalsection ofExecConfigoptional inschemas.pyfor situations where YAML configuration file is not provided. - Made
client_idandclient_secret_keyinCredentialsdefault to None. - Changed
parameters.time_scale_updatesreference toself.time_scale_updatesinmanager.py. - Updated code in
start_up()related to the definition of parameters to use_get_parameters_from_config()subclasses to customize parameter retrieval in:Applicationclass ofapplication.pyManagerclass ofmanager.pyManagedApplicationclass ofmanaged_application.py
- Updated
self.simulator.set_end_time(sim_stop_time)fromstop()inmanager.pyto run only ifself.simulator.get_mode() == Mode.EXECUTING - Removed
time_stepandmanager_app_namearguments fromstart_up()inManagerclass - Modified
set_wallclock_offset()insimulator.pyto allow setting wallclock offset when inMode.EXECUTING - Update default value of
time_status_inittodatetime.now()inApplicationConfigclass
Full Changelog: v2.2.0...v2.3.0
NOS-T Tools v2.2.0
Added:
- Introduced
TimeScaleUpdateSchemain schemas.py, which allows users to define time scale updates in the YAML configuration file atexecution.manager.time_scale_updates, each update can be defined bytime_scale_factorandsim_update_time. For example:time_scale_updates: - time_scale_factor: 120.0 sim_update_time: "2020-01-01T08:20:00+00:00"
NOTE: An example is provided in FireSat+ YAML configuration file.
- Introduced
get_app_specific_config()inconfiguration.pythat retrieves application-specific configuration from theexecution.managed_applicationssection based on the application name. - Added
application_configurationtoconfig.rc(runtime configuration) atconfiguration.py, which contains user-provided, application-specific configurations. These application-specific configurations can be defined for each application within the YAML configuration file at the fieldexecution.managed_applications.<application name>.configuration_parameters. This replacesconfig.pyfor each application in the NOS-T Tools examples.
Changed:
- Moved
self.establish_exchange()fromself._execute_test_plan_impl()toself.start_up()to prevent execution from starting before RabbitMQ exchanges have been declared and resulting in an error. - Removed conditional check for
self.app.channel.is_openandself.app.connection.is_openinapplication_utils.pybefore sending status messages; now assumes connection is always valid or managed externally. - Refactored the FireSat+, Downlink, Scalability, and scienceDash test suites to:
- Use a unified YAML configuration file per example
- Define application-specific settings under the
execution.managed_applications.<application name>.configuration_parametersfield instead of the previousconfig.py - Improve general code structure for enhanced efficiency, readability, and user experience
- Updated documentation for the FireSat+, Downlink, Scalability, and scienceDash test suites.
Full Changelog: v2.1.1...v2.2.0
NOS-T Tools v2.1.1
Added
- Introduces a new boolean flags to explicitly define the time domain for
time_stepandtime_status_step. These flags will determine whether the associated values are interpreted in scenario time (unscaled) or wall clock time (scaled by the time scale factor).
Full Changelog: v2.1.0...v2.1.1