iris-devtester 1.9.2__tar.gz → 1.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/AGENTS.md +129 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/PKG-INFO +84 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/README.md +83 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/SKILL.md +1 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/__init__.py +1 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/cli/container.py +228 -13
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/container_config.py +16 -11
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/container_state.py +6 -7
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/yaml_loader.py +1 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/iris_container.py +92 -13
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/ports/registry.py +2 -2
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester.egg-info/PKG-INFO +84 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/pyproject.toml +1 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/config/test_container_config.py +13 -2
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_iris_container.py +47 -3
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/utils/test_iris_container_adapter.py +1 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/CLAUDE.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/CONSTITUTION.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/LICENSE +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/MANIFEST.in +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/GETTING_STARTED.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/LANGCHAIN_INTEGRATION_QUICKSTART.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/ROADMAP.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/SQL_VS_OBJECTSCRIPT.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/TROUBLESHOOTING.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/WHATS_NEW_v1.4.0.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/AGENTIC_SANDBOX_ENHANCEMENT_REPORT.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/IMPACT_ANALYSIS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/IRIS_DEVTESTER_POSITIONING_REPORT.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/LANGCHAIN_INTEGRATION_STRATEGY.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/LANGCHAIN_INTEGRATION_TEST_RESULTS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/PHASE_2_PLAN.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/RAG_TEMPLATES_ANALYSIS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/README.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/STRATEGIC_ROADMAP_SUMMARY.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/archive/feature-009-refactor-plan.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/BUG_REPORT.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/EXTRACTION_SUMMARY.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/FEATURE_006_SUMMARY.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/PHASE2_RESULTS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/PRE_PUBLISH_REVIEW.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/PROGRESS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/PYPI_READINESS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/SESSION-INTEGRATION-TESTS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/SESSION-SUMMARY.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/STATUS-002-PIVOTED.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/STATUS-003-COMPLETE.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/STATUS.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/V1_COMPLETION_PLAN.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/development/V1_RELEASE_SUMMARY.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/features/WSGI-ASGI-SERVER-SETUP.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/features/agent-skills.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/features/dat-fixtures.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/features/docker-compose.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/features/performance-monitoring.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/features/testcontainers.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/api-contract-synchronization.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/callin-service-requirement.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/cpf-merge-and-container-restarts.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/dat-fixtures-docker-exec-pattern.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/dat-restore-database-isolation-problem.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/dbapi-bulk-insert-performance-issue.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/dbapi-objectscript-limitation.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/dbapi-password-reset-limitation.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/dbapi-private-module-myth.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/docker-hub-image-naming.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/embedded-python-considerations.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/feature-002-pivot-summary.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/integration-test-dbapi-limitation.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/iris-backup-patterns.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/iris-container-performance.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/iris-container-readiness.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/iris-docker-sdk-environment-variables.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/iris-performance-monitoring-landscape.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/iris-security-users-api.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/password-reset-changeflag-fix.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/rag-templates-production-patterns.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/sql-task-manager-operations.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/test-isolation-fix-summary.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/test-isolation-investigation.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/docs/learnings/testcontainers-ryuk-lifecycle.md +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/01_quickstart.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/02_connection_management.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/04_pytest_fixtures.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/05_ci_cd.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/08_auto_discovery.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/09_enterprise.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/10_docker_compose_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/examples/langchain_integration_example.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/cli/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/cli/__main__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/cli/connection_commands.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/cli/container_commands.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/cli/fixture_commands.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/auto_discovery.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/defaults.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/discovery.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/models.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/config/presets.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/__init__.py +1 -1
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/auto_discovery.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/connection.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/dbapi.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/jdbc.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/manager.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/models.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/connections/retry.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/cpf_manager.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/models.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/monitor_utils.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/monitoring.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/performance.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/validation.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/containers/wait_strategies.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/fixtures/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/fixtures/creator.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/fixtures/loader.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/fixtures/manifest.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/fixtures/obj_export.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/fixtures/validator.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/integrations/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/integrations/langchain.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/ports/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/ports/assignment.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/ports/exceptions.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/testing/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/testing/fixtures.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/testing/helpers.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/testing/models.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/testing/schema_reset.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/container_port.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/container_status.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/dbapi_compat.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/enable_callin.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/health_checks.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/iris_container_adapter.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/password.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/progress.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester/utils/test_connection.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester.egg-info/SOURCES.txt +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester.egg-info/dependency_links.txt +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester.egg-info/entry_points.txt +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester.egg-info/requires.txt +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/iris_devtester.egg-info/top_level.txt +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/setup.cfg +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/conftest.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_logs_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_remove_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_restart_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_start_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_status_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_stop_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/cli/test_container_up_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_agent_skills.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_cli_container_commands.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_cli_fixture_commands.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_connection_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_container_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_container_integration_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_container_status_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_container_validation_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_enable_callin_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_fixture_creator_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_fixture_loader_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_fixture_validator_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_iriscontainer_attach.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_legacy_package_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_modern_package_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_monitoring_config_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_package_detection.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_port_registry_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_preconfig_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_reset_verification_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_resource_monitoring_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_retry_logic_contract.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_task_manager_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_test_connection_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/contract/test_testing_fixtures_api.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/e2e/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/e2e/test_skill_workflow.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/conftest.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/ports/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/ports/test_manual_port_override.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/ports/test_multi_project_isolation.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/ports/test_port_exhaustion.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/ports/test_port_persistence.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/ports/test_stale_cleanup.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_bug_fixes.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_bug_fixes_011.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_cli_container_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_connection_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_container_health_monitor.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_container_status_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_container_validation.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_cpf_merge.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_cpf_presets.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_cpf_security.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_custom_user_remediation.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_dat_fixtures_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_enable_callin_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_fixture_export_patterns.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_fixture_performance.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_fixture_refresh.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_iriscontainer_attach_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_monitor_utils_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_monitoring_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_password_preconfig_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_password_reset_both_editions.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_password_reset_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_password_reset_macos.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_password_reset_timing.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_password_reset_validation.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_proactive_password_reset.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_real_world_problems.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_reliable_password_reset.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/integration/test_test_connection_integration.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/__init__.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/config/test_config_hierarchy.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/config/test_yaml_loader.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_auto_discovery.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_config_discovery.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_connection_fallback.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_connection_info.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_cpf_manager.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_iris_config.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_manifest.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_monitoring_policy.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_password_preconfig.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_password_preconfig_unit.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_performance_metrics.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_resource_thresholds.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_retry.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_schema_models.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_validation_results.py +0 -0
- {iris_devtester-1.9.2 → iris_devtester-1.10.0}/tests/unit/test_wait_strategies.py +0 -0
|
@@ -287,3 +287,132 @@ The repository exposes core functionality as "Skills" to help AI agents work aut
|
|
|
287
287
|
|
|
288
288
|
## Recent Changes
|
|
289
289
|
- 023-docs-cleanup: Added N/A (documentation only)
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## COMPOUND KNOWLEDGE BASE & DEVELOPMENT ENVIRONMENT
|
|
293
|
+
|
|
294
|
+
**Last Updated**: $(date +%Y-%m-%d)
|
|
295
|
+
|
|
296
|
+
> Central registry of development knowledge, tools, capabilities, and automation
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
### 📚 Knowledge Base
|
|
300
|
+
|
|
301
|
+
**Location**: `~/.config/opencode/compound-knowledge/`
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
**Structure**:
|
|
305
|
+
- `global/` - Project-agnostic knowledge (frameworks, tools, patterns)
|
|
306
|
+
- `projects/[name]/` - Project-specific knowledge (domain, architecture)
|
|
307
|
+
|
|
308
|
+
**Stats**: 7 solutions (7 global, 0 project)
|
|
309
|
+
|
|
310
|
+
**Quick Search**:
|
|
311
|
+
```bash
|
|
312
|
+
# Search everything
|
|
313
|
+
grep -ri "keywords" ~/.config/opencode/compound-knowledge/
|
|
314
|
+
|
|
315
|
+
# Global only
|
|
316
|
+
grep -ri "keywords" ~/.config/opencode/compound-knowledge/global/
|
|
317
|
+
|
|
318
|
+
# This project
|
|
319
|
+
grep -ri "keywords" ~/.config/opencode/compound-knowledge/projects/$(basename $(pwd))/
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Time Savings**: First solve: 30min → Next solve: 3min (90% faster)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
### 🔌 MCP Servers
|
|
326
|
+
|
|
327
|
+
- `atlassian` - local
|
|
328
|
+
- `gemini-impl` - local
|
|
329
|
+
- `hallucination-detector` - local
|
|
330
|
+
- `jama` - local
|
|
331
|
+
- `perplexity` - local
|
|
332
|
+
- `playwright` - local
|
|
333
|
+
- `qwen-impl` - local
|
|
334
|
+
- `support-tools` - local
|
|
335
|
+
|
|
336
|
+
### 🤖 Automation & Hooks
|
|
337
|
+
|
|
338
|
+
**Orchestrator Behavior** (configured via `~/.config/opencode/oh-my-opencode-slim.json`):
|
|
339
|
+
- **Before tasks**: Search compound KB for similar solutions
|
|
340
|
+
- **After completion**: Remind to document solution
|
|
341
|
+
|
|
342
|
+
**Periodic Maintenance** (recommended):
|
|
343
|
+
```bash
|
|
344
|
+
# Weekly: Regenerate KB index
|
|
345
|
+
~/.config/opencode/compound-knowledge/generate-index.sh
|
|
346
|
+
|
|
347
|
+
# Monthly: Review and consolidate similar solutions
|
|
348
|
+
# Quarterly: Extract patterns from repeated solutions
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Auto-Documentation Triggers**:
|
|
352
|
+
- Tests pass after fixing failure → Document solution
|
|
353
|
+
- Error resolved → Document fix
|
|
354
|
+
- Performance improved → Document optimization
|
|
355
|
+
- Integration working → Document configuration
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
### 🛠️ Tools & Utilities
|
|
359
|
+
|
|
360
|
+
**Compound Engineering**:
|
|
361
|
+
- `~/.config/opencode/compound-knowledge/new-solution.sh` - Create solution doc
|
|
362
|
+
- `~/.config/opencode/compound-knowledge/generate-index.sh` - Regenerate index
|
|
363
|
+
- `~/.config/opencode/compound-knowledge/sync-to-agents.sh` - Update AGENTS.md files
|
|
364
|
+
|
|
365
|
+
**OpenCode Agents** (oh-my-opencode-slim):
|
|
366
|
+
- `orchestrator` - Master coordinator (with compound engineering)
|
|
367
|
+
- `explorer` - Codebase reconnaissance
|
|
368
|
+
- `oracle` - Strategic advisor
|
|
369
|
+
- `librarian` - External knowledge (websearch, context7, grep_app MCPs)
|
|
370
|
+
- `designer` - UI/UX implementation
|
|
371
|
+
- `fixer` - Fast implementation
|
|
372
|
+
- `code-simplifier` - Post-work code refinement
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
### 🎯 Skills
|
|
376
|
+
|
|
377
|
+
**speckit** (feature specification):
|
|
378
|
+
- `speckit.plan` - Implementation planning
|
|
379
|
+
- `speckit.specify` - Feature specification
|
|
380
|
+
- `speckit.tasks` - Task generation
|
|
381
|
+
- `speckit.implement` - Implementation guidance
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
### 📋 Quick Reference
|
|
385
|
+
|
|
386
|
+
**Full Index**: `~/.config/opencode/compound-knowledge/INDEX.md`
|
|
387
|
+
|
|
388
|
+
**Documentation Templates**:
|
|
389
|
+
```markdown
|
|
390
|
+
---
|
|
391
|
+
title: "Problem description"
|
|
392
|
+
category: [build-errors|test-failures|runtime-errors|performance-issues|
|
|
393
|
+
database-issues|security-issues|ui-bugs|integration-issues|logic-errors]
|
|
394
|
+
date: YYYY-MM-DD
|
|
395
|
+
severity: high|medium|low
|
|
396
|
+
tags: [tag1, tag2]
|
|
397
|
+
time_to_solve: XXmin
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Problem Symptom
|
|
401
|
+
[What was observed]
|
|
402
|
+
|
|
403
|
+
## Solution
|
|
404
|
+
[How you fixed it]
|
|
405
|
+
|
|
406
|
+
## Prevention
|
|
407
|
+
[How to avoid future]
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Decision Tree** (Global vs Project-Specific):
|
|
411
|
+
- Framework/tool issue → `global/`
|
|
412
|
+
- General pattern → `global/`
|
|
413
|
+
- Project domain logic → `projects/[name]/`
|
|
414
|
+
- Project architecture → `projects/[name]/`
|
|
415
|
+
- When in doubt → `global/`
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iris-devtester
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.0
|
|
4
4
|
Summary: Battle-tested InterSystems IRIS infrastructure utilities for Python development
|
|
5
5
|
Author-email: InterSystems Community <community@intersystems.com>
|
|
6
6
|
Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
|
|
@@ -107,6 +107,89 @@ def test_connection():
|
|
|
107
107
|
assert cursor.fetchone()[0] == 1
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
## Container Editions
|
|
111
|
+
|
|
112
|
+
Three canonical container editions are available:
|
|
113
|
+
|
|
114
|
+
| Edition | Size | Use Case | Image |
|
|
115
|
+
|---------|------|----------|-------|
|
|
116
|
+
| **Community** | ~972MB | Development, testing | `intersystemsdc/iris-community` |
|
|
117
|
+
| **Enterprise** | ~1GB+ | Production testing | `containers.intersystems.com/intersystems/iris` |
|
|
118
|
+
| **Light** | **~580MB** | CI/CD pipelines | `caretdev/iris-community-light` |
|
|
119
|
+
|
|
120
|
+
### Python API
|
|
121
|
+
```python
|
|
122
|
+
from iris_devtester.containers import IRISContainer
|
|
123
|
+
|
|
124
|
+
# Community Edition (auto-detects ARM64 vs x86)
|
|
125
|
+
with IRISContainer.community() as iris:
|
|
126
|
+
conn = iris.get_connection()
|
|
127
|
+
|
|
128
|
+
# Light Edition (85% smaller, for CI/CD)
|
|
129
|
+
with IRISContainer.light() as iris:
|
|
130
|
+
conn = iris.get_connection()
|
|
131
|
+
|
|
132
|
+
# Enterprise Edition (requires license)
|
|
133
|
+
with IRISContainer.enterprise(license_key="/path/to/iris.key") as iris:
|
|
134
|
+
conn = iris.get_connection()
|
|
135
|
+
|
|
136
|
+
# Specify version
|
|
137
|
+
with IRISContainer.community(version="2025.1") as iris:
|
|
138
|
+
conn = iris.get_connection()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### CLI Usage
|
|
142
|
+
```bash
|
|
143
|
+
# Community (default)
|
|
144
|
+
iris-devtester container up
|
|
145
|
+
|
|
146
|
+
# Light edition for CI/CD
|
|
147
|
+
iris-devtester container up --edition light
|
|
148
|
+
|
|
149
|
+
# Enterprise edition with license
|
|
150
|
+
iris-devtester container up --edition enterprise --license /path/to/iris.key
|
|
151
|
+
|
|
152
|
+
# List running IRIS containers
|
|
153
|
+
iris-devtester container list
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Light Edition Details
|
|
157
|
+
|
|
158
|
+
The Light edition removes components unnecessary for SQL-only workloads:
|
|
159
|
+
- **Removed**: Interoperability/Ensemble, Management Portal, DeepSee/BI, CSP/REST
|
|
160
|
+
- **Kept**: SQL engine, DBAPI, JDBC, ODBC, SQLAlchemy-IRIS support
|
|
161
|
+
|
|
162
|
+
Perfect for microservices, automated testing, and Python/SQL pipelines.
|
|
163
|
+
|
|
164
|
+
### Builder Methods
|
|
165
|
+
```python
|
|
166
|
+
# Set a custom container name (for debugging, logs, multiple containers)
|
|
167
|
+
iris = IRISContainer.community().with_name("my-test-db")
|
|
168
|
+
|
|
169
|
+
# Set credentials
|
|
170
|
+
iris = IRISContainer.community().with_credentials("_SYSTEM", "MyPassword")
|
|
171
|
+
|
|
172
|
+
# Pre-configure password (set via IRIS_PASSWORD env var at startup)
|
|
173
|
+
iris = IRISContainer.community().with_preconfigured_password("MyPassword")
|
|
174
|
+
|
|
175
|
+
# Chain multiple options
|
|
176
|
+
with IRISContainer.community() \
|
|
177
|
+
.with_name("integration-test-db") \
|
|
178
|
+
.with_credentials("_SYSTEM", "TestPass123") as iris:
|
|
179
|
+
conn = iris.get_connection()
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Constructor Parameters
|
|
183
|
+
```python
|
|
184
|
+
IRISContainer(
|
|
185
|
+
image="intersystemsdc/iris-community:latest", # Docker image
|
|
186
|
+
username="SuperUser", # Default username
|
|
187
|
+
password="SYS", # Default password
|
|
188
|
+
namespace="USER", # Default namespace
|
|
189
|
+
name="my-container", # Container name (alternative to with_name)
|
|
190
|
+
)
|
|
191
|
+
```
|
|
192
|
+
|
|
110
193
|
## Key Features
|
|
111
194
|
|
|
112
195
|
- **🔐 Automatic Password Management**: Remediates security flags using official system APIs.
|
|
@@ -43,6 +43,89 @@ def test_connection():
|
|
|
43
43
|
assert cursor.fetchone()[0] == 1
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## Container Editions
|
|
47
|
+
|
|
48
|
+
Three canonical container editions are available:
|
|
49
|
+
|
|
50
|
+
| Edition | Size | Use Case | Image |
|
|
51
|
+
|---------|------|----------|-------|
|
|
52
|
+
| **Community** | ~972MB | Development, testing | `intersystemsdc/iris-community` |
|
|
53
|
+
| **Enterprise** | ~1GB+ | Production testing | `containers.intersystems.com/intersystems/iris` |
|
|
54
|
+
| **Light** | **~580MB** | CI/CD pipelines | `caretdev/iris-community-light` |
|
|
55
|
+
|
|
56
|
+
### Python API
|
|
57
|
+
```python
|
|
58
|
+
from iris_devtester.containers import IRISContainer
|
|
59
|
+
|
|
60
|
+
# Community Edition (auto-detects ARM64 vs x86)
|
|
61
|
+
with IRISContainer.community() as iris:
|
|
62
|
+
conn = iris.get_connection()
|
|
63
|
+
|
|
64
|
+
# Light Edition (85% smaller, for CI/CD)
|
|
65
|
+
with IRISContainer.light() as iris:
|
|
66
|
+
conn = iris.get_connection()
|
|
67
|
+
|
|
68
|
+
# Enterprise Edition (requires license)
|
|
69
|
+
with IRISContainer.enterprise(license_key="/path/to/iris.key") as iris:
|
|
70
|
+
conn = iris.get_connection()
|
|
71
|
+
|
|
72
|
+
# Specify version
|
|
73
|
+
with IRISContainer.community(version="2025.1") as iris:
|
|
74
|
+
conn = iris.get_connection()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### CLI Usage
|
|
78
|
+
```bash
|
|
79
|
+
# Community (default)
|
|
80
|
+
iris-devtester container up
|
|
81
|
+
|
|
82
|
+
# Light edition for CI/CD
|
|
83
|
+
iris-devtester container up --edition light
|
|
84
|
+
|
|
85
|
+
# Enterprise edition with license
|
|
86
|
+
iris-devtester container up --edition enterprise --license /path/to/iris.key
|
|
87
|
+
|
|
88
|
+
# List running IRIS containers
|
|
89
|
+
iris-devtester container list
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Light Edition Details
|
|
93
|
+
|
|
94
|
+
The Light edition removes components unnecessary for SQL-only workloads:
|
|
95
|
+
- **Removed**: Interoperability/Ensemble, Management Portal, DeepSee/BI, CSP/REST
|
|
96
|
+
- **Kept**: SQL engine, DBAPI, JDBC, ODBC, SQLAlchemy-IRIS support
|
|
97
|
+
|
|
98
|
+
Perfect for microservices, automated testing, and Python/SQL pipelines.
|
|
99
|
+
|
|
100
|
+
### Builder Methods
|
|
101
|
+
```python
|
|
102
|
+
# Set a custom container name (for debugging, logs, multiple containers)
|
|
103
|
+
iris = IRISContainer.community().with_name("my-test-db")
|
|
104
|
+
|
|
105
|
+
# Set credentials
|
|
106
|
+
iris = IRISContainer.community().with_credentials("_SYSTEM", "MyPassword")
|
|
107
|
+
|
|
108
|
+
# Pre-configure password (set via IRIS_PASSWORD env var at startup)
|
|
109
|
+
iris = IRISContainer.community().with_preconfigured_password("MyPassword")
|
|
110
|
+
|
|
111
|
+
# Chain multiple options
|
|
112
|
+
with IRISContainer.community() \
|
|
113
|
+
.with_name("integration-test-db") \
|
|
114
|
+
.with_credentials("_SYSTEM", "TestPass123") as iris:
|
|
115
|
+
conn = iris.get_connection()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Constructor Parameters
|
|
119
|
+
```python
|
|
120
|
+
IRISContainer(
|
|
121
|
+
image="intersystemsdc/iris-community:latest", # Docker image
|
|
122
|
+
username="SuperUser", # Default username
|
|
123
|
+
password="SYS", # Default password
|
|
124
|
+
namespace="USER", # Default namespace
|
|
125
|
+
name="my-container", # Container name (alternative to with_name)
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
46
129
|
## Key Features
|
|
47
130
|
|
|
48
131
|
- **🔐 Automatic Password Management**: Remediates security flags using official system APIs.
|
|
@@ -3,7 +3,7 @@ name: iris-devtester
|
|
|
3
3
|
description: Battle-tested InterSystems IRIS infrastructure utilities for Python database testing.
|
|
4
4
|
triggers: [iris, database, testing, container, fixture, gof, connection, remediation]
|
|
5
5
|
metadata:
|
|
6
|
-
version: 1.
|
|
6
|
+
version: 1.10.0
|
|
7
7
|
author: InterSystems Community
|
|
8
8
|
principles: [library-first, dbapi-first, isolation-by-default, fail-fast]
|
|
9
9
|
---
|
|
@@ -31,6 +31,25 @@ def container_group(ctx):
|
|
|
31
31
|
@click.option(
|
|
32
32
|
"--config", type=click.Path(exists=True), help="Path to iris-config.yml configuration file"
|
|
33
33
|
)
|
|
34
|
+
@click.option(
|
|
35
|
+
"--name",
|
|
36
|
+
type=str,
|
|
37
|
+
default=None,
|
|
38
|
+
help="Container name (default: iris_db)",
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
"--edition",
|
|
42
|
+
type=click.Choice(["community", "enterprise", "light"], case_sensitive=False),
|
|
43
|
+
default="community",
|
|
44
|
+
help="IRIS edition: community (default), enterprise (requires license), light (minimal for CI/CD)",
|
|
45
|
+
)
|
|
46
|
+
@click.option(
|
|
47
|
+
"--license",
|
|
48
|
+
"license_key",
|
|
49
|
+
type=click.Path(exists=True),
|
|
50
|
+
default=None,
|
|
51
|
+
help="Path to iris.key license file (required for enterprise edition)",
|
|
52
|
+
)
|
|
34
53
|
@click.option(
|
|
35
54
|
"--detach/--no-detach",
|
|
36
55
|
default=True,
|
|
@@ -41,7 +60,7 @@ def container_group(ctx):
|
|
|
41
60
|
)
|
|
42
61
|
@click.option("--cpf", help="Path to CPF merge file or raw CPF content")
|
|
43
62
|
@click.pass_context
|
|
44
|
-
def up(ctx, config, detach, timeout, cpf):
|
|
63
|
+
def up(ctx, config, name, edition, license_key, detach, timeout, cpf):
|
|
45
64
|
"""
|
|
46
65
|
Create and start IRIS container from configuration.
|
|
47
66
|
|
|
@@ -58,15 +77,18 @@ def up(ctx, config, detach, timeout, cpf):
|
|
|
58
77
|
# Zero-config (uses Community edition defaults)
|
|
59
78
|
iris-devtester container up
|
|
60
79
|
|
|
80
|
+
# Light edition for CI/CD (85% smaller, faster startup)
|
|
81
|
+
iris-devtester container up --edition light
|
|
82
|
+
|
|
83
|
+
# Enterprise edition with license
|
|
84
|
+
iris-devtester container up --edition enterprise --license /path/to/iris.key
|
|
85
|
+
|
|
86
|
+
# With custom container name
|
|
87
|
+
iris-devtester container up --name my-test-db
|
|
88
|
+
|
|
61
89
|
# With custom configuration including volumes
|
|
62
90
|
iris-devtester container up --config iris-config.yml
|
|
63
91
|
|
|
64
|
-
# Example iris-config.yml with volumes:
|
|
65
|
-
# edition: community
|
|
66
|
-
# volumes:
|
|
67
|
-
# - ./workspace:/external/workspace
|
|
68
|
-
# - ./config:/opt/config:ro
|
|
69
|
-
|
|
70
92
|
# Foreground mode (see logs)
|
|
71
93
|
iris-devtester container up --no-detach
|
|
72
94
|
"""
|
|
@@ -85,6 +107,37 @@ def up(ctx, config, detach, timeout, cpf):
|
|
|
85
107
|
container_config = ContainerConfig.default()
|
|
86
108
|
click.echo("⚡ Creating container from zero-config defaults")
|
|
87
109
|
|
|
110
|
+
# Override container name if provided via --name
|
|
111
|
+
if name:
|
|
112
|
+
container_config.container_name = name
|
|
113
|
+
click.echo(f" → Container name: {name}")
|
|
114
|
+
|
|
115
|
+
# Override edition if provided via --edition
|
|
116
|
+
if edition:
|
|
117
|
+
edition_lower = edition.lower()
|
|
118
|
+
container_config.edition = edition_lower
|
|
119
|
+
|
|
120
|
+
# Set appropriate image based on edition
|
|
121
|
+
if edition_lower == "light":
|
|
122
|
+
# Light edition: caretdev/iris-community-light (85% smaller)
|
|
123
|
+
container_config.image_tag = "latest-em"
|
|
124
|
+
click.echo(
|
|
125
|
+
click.style(f" → Edition: light", fg="cyan")
|
|
126
|
+
+ " (minimal for CI/CD, ~580MB vs ~3.5GB)"
|
|
127
|
+
)
|
|
128
|
+
elif edition_lower == "enterprise":
|
|
129
|
+
if not license_key:
|
|
130
|
+
raise click.ClickException(
|
|
131
|
+
"Enterprise edition requires --license option.\n"
|
|
132
|
+
"\n"
|
|
133
|
+
"Usage: iris-devtester container up --edition enterprise --license /path/to/iris.key"
|
|
134
|
+
)
|
|
135
|
+
container_config.license_key = license_key
|
|
136
|
+
click.echo(f" → Edition: enterprise")
|
|
137
|
+
click.echo(f" → License: {license_key}")
|
|
138
|
+
else:
|
|
139
|
+
click.echo(f" → Edition: community")
|
|
140
|
+
|
|
88
141
|
if cpf:
|
|
89
142
|
container_config.cpf_merge = cpf
|
|
90
143
|
click.echo(f" → CPF Merge: {cpf[:50]}...")
|
|
@@ -95,6 +148,36 @@ def up(ctx, config, detach, timeout, cpf):
|
|
|
95
148
|
if existing_container:
|
|
96
149
|
# Container exists - check if running
|
|
97
150
|
existing_container.reload()
|
|
151
|
+
|
|
152
|
+
# Warn if using default name and container already exists
|
|
153
|
+
# (user might be connecting to wrong container from different project)
|
|
154
|
+
if container_config.container_name == "iris_db" and not name:
|
|
155
|
+
existing_image = (
|
|
156
|
+
existing_container.image.tags[0] if existing_container.image.tags else "unknown"
|
|
157
|
+
)
|
|
158
|
+
click.echo("")
|
|
159
|
+
click.echo(
|
|
160
|
+
click.style(
|
|
161
|
+
"⚠️ WARNING: Using default container name 'iris_db'", fg="yellow", bold=True
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
click.echo(
|
|
165
|
+
click.style(
|
|
166
|
+
f" A container with this name already exists (image: {existing_image})",
|
|
167
|
+
fg="yellow",
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
click.echo(
|
|
171
|
+
click.style(
|
|
172
|
+
" If this is from a different project, use --name to avoid conflicts:",
|
|
173
|
+
fg="yellow",
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
click.echo(
|
|
177
|
+
click.style(" iris-devtester container up --name my-project-db", fg="cyan")
|
|
178
|
+
)
|
|
179
|
+
click.echo("")
|
|
180
|
+
|
|
98
181
|
if existing_container.status == "running":
|
|
99
182
|
click.echo(f"✓ Container '{container_config.container_name}' is already running")
|
|
100
183
|
|
|
@@ -228,6 +311,141 @@ def up(ctx, config, detach, timeout, cpf):
|
|
|
228
311
|
ctx.exit(1)
|
|
229
312
|
|
|
230
313
|
|
|
314
|
+
@container_group.command(name="list")
|
|
315
|
+
@click.option(
|
|
316
|
+
"--all", "-a", "show_all", is_flag=True, help="Show all containers (including stopped)"
|
|
317
|
+
)
|
|
318
|
+
@click.option(
|
|
319
|
+
"--format",
|
|
320
|
+
"output_format",
|
|
321
|
+
type=click.Choice(["table", "json"], case_sensitive=False),
|
|
322
|
+
default="table",
|
|
323
|
+
help="Output format (default: table)",
|
|
324
|
+
)
|
|
325
|
+
@click.pass_context
|
|
326
|
+
def list_containers(ctx, show_all, output_format):
|
|
327
|
+
"""
|
|
328
|
+
List IRIS containers.
|
|
329
|
+
|
|
330
|
+
Shows all IRIS containers managed by iris-devtester, with their status,
|
|
331
|
+
edition, ports, and age.
|
|
332
|
+
|
|
333
|
+
\b
|
|
334
|
+
Examples:
|
|
335
|
+
# List running containers
|
|
336
|
+
iris-devtester container list
|
|
337
|
+
|
|
338
|
+
# List all containers (including stopped)
|
|
339
|
+
iris-devtester container list --all
|
|
340
|
+
|
|
341
|
+
# JSON output for scripting
|
|
342
|
+
iris-devtester container list --format json
|
|
343
|
+
"""
|
|
344
|
+
from datetime import datetime
|
|
345
|
+
|
|
346
|
+
import docker
|
|
347
|
+
|
|
348
|
+
try:
|
|
349
|
+
client = docker.from_env()
|
|
350
|
+
|
|
351
|
+
# Find IRIS containers (by image name patterns)
|
|
352
|
+
iris_patterns = [
|
|
353
|
+
"iris-community",
|
|
354
|
+
"intersystems/iris",
|
|
355
|
+
"caretdev/iris",
|
|
356
|
+
"intersystemsdc/iris",
|
|
357
|
+
]
|
|
358
|
+
|
|
359
|
+
containers = client.containers.list(all=show_all)
|
|
360
|
+
iris_containers = []
|
|
361
|
+
|
|
362
|
+
for container in containers:
|
|
363
|
+
image_name = (
|
|
364
|
+
container.image.tags[0] if container.image.tags else str(container.image.id)[:12]
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
# Check if this is an IRIS container
|
|
368
|
+
is_iris = any(pattern in image_name.lower() for pattern in iris_patterns)
|
|
369
|
+
if not is_iris:
|
|
370
|
+
continue
|
|
371
|
+
|
|
372
|
+
# Determine edition from image name
|
|
373
|
+
if "light" in image_name.lower():
|
|
374
|
+
edition = "light"
|
|
375
|
+
elif "community" in image_name.lower():
|
|
376
|
+
edition = "community"
|
|
377
|
+
else:
|
|
378
|
+
edition = "enterprise"
|
|
379
|
+
|
|
380
|
+
# Get port mappings
|
|
381
|
+
ports = container.attrs.get("NetworkSettings", {}).get("Ports", {})
|
|
382
|
+
port_str = "-"
|
|
383
|
+
if ports and ports.get("1972/tcp"):
|
|
384
|
+
host_port = ports["1972/tcp"][0]["HostPort"]
|
|
385
|
+
port_str = f"{host_port}->1972"
|
|
386
|
+
|
|
387
|
+
# Calculate age
|
|
388
|
+
created = container.attrs.get("Created", "")
|
|
389
|
+
age_str = "unknown"
|
|
390
|
+
if created:
|
|
391
|
+
try:
|
|
392
|
+
# Parse ISO format timestamp
|
|
393
|
+
created_dt = datetime.fromisoformat(created.replace("Z", "+00:00"))
|
|
394
|
+
now = datetime.now(created_dt.tzinfo)
|
|
395
|
+
delta = now - created_dt
|
|
396
|
+
if delta.days > 0:
|
|
397
|
+
age_str = f"{delta.days}d"
|
|
398
|
+
elif delta.seconds > 3600:
|
|
399
|
+
age_str = f"{delta.seconds // 3600}h"
|
|
400
|
+
else:
|
|
401
|
+
age_str = f"{delta.seconds // 60}m"
|
|
402
|
+
except Exception:
|
|
403
|
+
pass
|
|
404
|
+
|
|
405
|
+
iris_containers.append(
|
|
406
|
+
{
|
|
407
|
+
"name": container.name,
|
|
408
|
+
"edition": edition,
|
|
409
|
+
"status": container.status,
|
|
410
|
+
"ports": port_str,
|
|
411
|
+
"age": age_str,
|
|
412
|
+
"image": image_name,
|
|
413
|
+
}
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
if output_format == "json":
|
|
417
|
+
import json as json_module
|
|
418
|
+
|
|
419
|
+
click.echo(json_module.dumps(iris_containers, indent=2))
|
|
420
|
+
else:
|
|
421
|
+
# Table format
|
|
422
|
+
if not iris_containers:
|
|
423
|
+
click.echo("No IRIS containers found.")
|
|
424
|
+
if not show_all:
|
|
425
|
+
click.echo("Use --all to include stopped containers.")
|
|
426
|
+
else:
|
|
427
|
+
# Print header
|
|
428
|
+
click.echo(f"{'NAME':<20} {'EDITION':<12} {'STATUS':<10} {'PORTS':<15} {'AGE':<6}")
|
|
429
|
+
click.echo("-" * 65)
|
|
430
|
+
|
|
431
|
+
for c in iris_containers:
|
|
432
|
+
status_color = "green" if c["status"] == "running" else "yellow"
|
|
433
|
+
click.echo(
|
|
434
|
+
f"{c['name']:<20} "
|
|
435
|
+
f"{c['edition']:<12} "
|
|
436
|
+
f"{click.style(c['status'], fg=status_color):<19} "
|
|
437
|
+
f"{c['ports']:<15} "
|
|
438
|
+
f"{c['age']:<6}"
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
except docker.errors.DockerException as e:
|
|
442
|
+
progress.print_error(f"Docker error: {e}")
|
|
443
|
+
ctx.exit(1)
|
|
444
|
+
except Exception as e:
|
|
445
|
+
progress.print_error(f"Error listing containers: {e}")
|
|
446
|
+
ctx.exit(1)
|
|
447
|
+
|
|
448
|
+
|
|
231
449
|
@container_group.command(name="start")
|
|
232
450
|
@click.argument("container_name", required=False, default="iris_db")
|
|
233
451
|
@click.option(
|
|
@@ -613,7 +831,7 @@ def remove(ctx, container_name, force, volumes):
|
|
|
613
831
|
|
|
614
832
|
|
|
615
833
|
@container_group.command(name="reset-password")
|
|
616
|
-
@click.argument("container_name")
|
|
834
|
+
@click.argument("container_name", required=False, default="iris_db")
|
|
617
835
|
@click.option("--user", default="_SYSTEM", help="Username to reset password for (default: _SYSTEM)")
|
|
618
836
|
@click.option("--password", default="SYS", help="New password (default: SYS)")
|
|
619
837
|
@click.option(
|
|
@@ -679,7 +897,7 @@ def reset_password_cmd(ctx, container_name, user, password, port):
|
|
|
679
897
|
|
|
680
898
|
|
|
681
899
|
@container_group.command(name="test-connection")
|
|
682
|
-
@click.argument("container_name")
|
|
900
|
+
@click.argument("container_name", required=False, default="iris_db")
|
|
683
901
|
@click.option(
|
|
684
902
|
"--namespace", default="USER", help="IRIS namespace to test connection to (default: USER)"
|
|
685
903
|
)
|
|
@@ -768,7 +986,7 @@ def test_connection_cmd(ctx, container_name, namespace, username, password):
|
|
|
768
986
|
|
|
769
987
|
|
|
770
988
|
@container_group.command(name="enable-callin")
|
|
771
|
-
@click.argument("container_name")
|
|
989
|
+
@click.argument("container_name", required=False, default="iris_db")
|
|
772
990
|
@click.option(
|
|
773
991
|
"--timeout", type=int, default=30, help="Timeout in seconds for docker commands (default: 30)"
|
|
774
992
|
)
|
|
@@ -808,9 +1026,6 @@ def enable_callin(ctx, container_name, timeout):
|
|
|
808
1026
|
except (ImportError, ModuleNotFoundError) as e:
|
|
809
1027
|
progress.print_error(f"enable_callin utility not available: {e}")
|
|
810
1028
|
ctx.exit(1)
|
|
811
|
-
except (click.exceptions.Exit, SystemExit, KeyboardInterrupt):
|
|
812
|
-
# Let Click handle these - don't catch them
|
|
813
|
-
raise
|
|
814
1029
|
except Exception as e:
|
|
815
1030
|
progress.print_error(f"Failed to enable CallIn: {e}")
|
|
816
1031
|
ctx.exit(1)
|