Skip to content

Commit 3bd8cf0

Browse files
Merge branch 'master' of github.com:SyntaxArc/ArchiPy
2 parents 65a4a93 + 2197750 commit 3bd8cf0

15 files changed

Lines changed: 1710 additions & 684 deletions

.env.test

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,40 @@ FASTAPI__DOCS_URL="/docs"
1515
FASTAPI__RE_DOCS_URL="/redoc"
1616
FASTAPI__SWAGGER_UI_PARAMS={}
1717

18-
KEYCLOAK__SERVER_URL="https://localhost"
19-
KEYCLOAK__VERIFY_SSL=False
20-
KEYCLOAK__ADMIN_USERNAME="admin"
21-
KEYCLOAK__ADMIN_PASSWORD="admin"
22-
KEYCLOAK__ADMIN_REALM_NAME="master"
18+
# Redis Configuration (RedisConfig)
19+
REDIS__MASTER_HOST=localhost:6379
20+
REDIS__IMAGE=redis:7-alpine
21+
REDIS__DATABASE=0
22+
REDIS__PASSWORD=test_password
2323

24-
MINIO__ENDPOINT=localhost:9000
25-
MINIO__ACCESS_KEY=HWQVccFGoSztcyiEYOqE
26-
MINIO__SECRET_KEY=XCnmAX8BrlFSK4zLWGSkJuTdZBelrTpnbOTowSUs
24+
# PostgreSQL Configuration
25+
POSTGRES__IMAGE=postgres:17
26+
POSTGRES_SQLALCHEMY__HOST=localhost
27+
POSTGRES_SQLALCHEMY__PORT=5432
28+
POSTGRES_SQLALCHEMY__DATABASE=test_db
29+
POSTGRES_SQLALCHEMY__USERNAME=test_user
30+
POSTGRES_SQLALCHEMY__PASSWORD=test_password
31+
32+
# Keycloak Configuration (KeycloakConfig)
33+
KEYCLOAK__SERVER_URL=http://localhost:8080
34+
KEYCLOAK__IMAGE=quay.io/keycloak/keycloak:23.0
35+
KEYCLOAK__ADMIN_USERNAME=admin
36+
KEYCLOAK__ADMIN_PASSWORD=admin
37+
KEYCLOAK__REALM_NAME=master
38+
39+
# Elasticsearch Configuration (ElasticsearchConfig)
40+
ELASTIC__HOSTS=["http://localhost:9200"]
41+
ELASTIC__IMAGE=repo.smartech.ir/elasticsearch/elasticsearch:9.1.0
42+
ELASTIC__PORT=9200
43+
ELASTIC__HTTP_USER_NAME=elastic
44+
ELASTIC__HTTP_PASSWORD=test_password
2745

46+
# Kafka Configuration (KafkaConfig)
47+
KAFKA__IMAGE=confluentinc/cp-kafka:7.4.0
2848
KAFKA__BROKERS_LIST=["localhost:9092"]
49+
50+
# MinIO Configuration (MinioConfig)
51+
MINIO__ENDPOINT=localhost:9000
52+
MINIO__IMAGE=quay.io/minio/minio:latest
53+
MINIO__ACCESS_KEY=test_access_key
54+
MINIO__SECRET_KEY=test_secret_key

.github/workflows/bandit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333

3434
runs-on: ubuntu-latest
3535
steps:
36-
- uses: actions/checkout@v4
36+
- uses: actions/checkout@v5
3737
- name: Bandit Scan
3838
uses: shundor/python-bandit-scan@ab1d87dfccc5a0ffab88be3aaac6ffe35c10d6cd
3939
with: # optional arguments

.github/workflows/deploy-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
runs-on: ubuntu-latest
1919
steps:
2020
- name: Checkout repository
21-
uses: actions/checkout@v4
21+
uses: actions/checkout@v5
2222
with:
2323
fetch-depth: 0 # Fetch all history for proper versioning
2424

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
lint:
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v4
13+
- uses: actions/checkout@v5
1414
with:
1515
fetch-depth: 0
1616

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout code
13-
uses: actions/checkout@v4
13+
uses: actions/checkout@v5
1414

1515
- name: Set up Python
1616
uses: actions/setup-python@v5

archipy/adapters/elasticsearch/adapters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def _get_client(configs: ElasticsearchConfig) -> Elasticsearch:
5252
if configs.API_KEY and configs.API_SECRET:
5353
api_key = ((configs.API_KEY, configs.API_SECRET),)
5454
elif configs.HTTP_USER_NAME and configs.HTTP_PASSWORD:
55-
basic_auth = ((configs.HTTP_USER_NAME, configs.HTTP_PASSWORD.get_secret_value()),)
55+
basic_auth = (configs.HTTP_USER_NAME, configs.HTTP_PASSWORD.get_secret_value())
5656

5757
return Elasticsearch(
5858
hosts=configs.HOSTS,

archipy/helpers/utils/password_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def validate_password_history(
161161
configs = auth_config or BaseConfig.global_config().AUTH
162162

163163
# First validate against password policy
164-
cls.validate_password(new_password, configs, lang)
164+
cls.validate_password(new_password, configs)
165165

166166
# Check password history
167167
if any(

features/elastic_adapter.feature

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,34 @@ Feature: Elasticsearch Operations Testing
66

77
Background:
88
Given an Elasticsearch cluster is running
9-
And index "test-index" exists
109
And document type "test-doc" is configured for index "test-index"
1110

1211
Scenario: Index a new document synchronously
1312
Given a valid Elasticsearch client connection
13+
And index "test-index" exists
1414
When I index a document with id "1" and content '{"title": "Test Document", "content": "This is a test"}' into "test-index"
1515
Then the indexing operation should succeed
1616
And the document should be retrievable by id "1" from "test-index"
1717

1818
Scenario: Search for documents synchronously
1919
Given a valid Elasticsearch client connection
20+
And index "test-index" exists
2021
And a document exists in "test-index" with id "1" and content '{"title": "Test Document", "content": "This is a test"}'
2122
When I search for "Test Document" in "test-index"
2223
Then the search should return at least 1 hit
2324
And the hit should contain field "title" with value "Test Document"
2425

2526
Scenario: Update a document synchronously
2627
Given a valid Elasticsearch client connection
28+
And index "test-index" exists
2729
And a document exists in "test-index" with id "1" and content '{"title": "Test Document", "content": "This is a test"}'
28-
When I update document "1" in "test-index" with content '{"title": "Updated Document", "content": "This is an update"}'
30+
When I update document "1" in "test-index" with content '{"doc": {"title": "Updated Document", "content": "This is an update"}}'
2931
Then the update operation should succeed
3032
And the document should reflect the updated content when retrieved
3133

3234
Scenario: Delete a document synchronously
3335
Given a valid Elasticsearch client connection
36+
And index "test-index" exists
3437
And a document exists in "test-index" with id "1" and content '{"title": "Test Document", "content": "This is a test"}'
3538
When I delete document "1" from "test-index"
3639
Then the delete operation should succeed
@@ -51,6 +54,8 @@ Feature: Elasticsearch Operations Testing
5154

5255
Scenario: Perform bulk operations synchronously
5356
Given a valid Elasticsearch client connection
57+
And index "test-index" exists
58+
And a document exists in "test-index" with id "1" and content '{"title": "Test Document", "content": "This is a test"}'
5459
When I perform a bulk operation with:
5560
| action | id | index | document |
5661
| index | 2 | test-index | {"title": "Doc 2", "content": "Second"} |
@@ -63,13 +68,15 @@ Feature: Elasticsearch Operations Testing
6368
@async
6469
Scenario: Index a new document asynchronously
6570
Given a valid Elasticsearch client connection
71+
And index "test-index" exists
6672
When I index a document with id "10" and content '{"title": "Async Doc", "content": "Async test"}' into "test-index"
6773
Then the indexing operation should succeed
6874
And the document should be retrievable by id "10" from "test-index"
6975

7076
@async
7177
Scenario: Search for documents asynchronously
7278
Given a valid Elasticsearch client connection
79+
And index "test-index" exists
7380
And a document exists in "test-index" with id "10" and content '{"title": "Async Doc", "content": "Async test"}'
7481
When I search for "Async Doc" in "test-index"
7582
Then the search should return at least 1 hit
@@ -78,14 +85,16 @@ Feature: Elasticsearch Operations Testing
7885
@async
7986
Scenario: Update a document asynchronously
8087
Given a valid Elasticsearch client connection
88+
And index "test-index" exists
8189
And a document exists in "test-index" with id "10" and content '{"title": "Async Doc", "content": "Async test"}'
82-
When I update document "10" in "test-index" with content '{"title": "Updated Async", "content": "Updated async"}'
90+
When I update document "10" in "test-index" with content '{"doc": {"title": "Updated Async", "content": "Updated async"}}'
8391
Then the update operation should succeed
8492
And the document should reflect the updated content when retrieved
8593

8694
@async
8795
Scenario: Delete a document asynchronously
8896
Given a valid Elasticsearch client connection
97+
And index "test-index" exists
8998
And a document exists in "test-index" with id "10" and content '{"title": "Async Doc", "content": "Async test"}'
9099
When I delete document "10" from "test-index"
91100
Then the delete operation should succeed
@@ -109,6 +118,8 @@ Feature: Elasticsearch Operations Testing
109118
@async
110119
Scenario: Perform bulk operations asynchronously
111120
Given a valid Elasticsearch client connection
121+
And index "test-index" exists
122+
And a document exists in "test-index" with id "10" and content '{"title": "Async Doc", "content": "Async test"}'
112123
When I perform a bulk operation with:
113124
| action | id | index | document |
114125
| index | 20 | test-index | {"title": "Async 2", "content": "Second"} |
@@ -122,4 +133,4 @@ Feature: Elasticsearch Operations Testing
122133
Given an Elasticsearch cluster with security enabled
123134
When I connect with username "elastic-user" and password "elastic-pass"
124135
Then the connection should be successful
125-
And I should be able to perform operations on the cluster
136+
And I should be able to perform operations on the cluster

features/environment.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
and handling async operations.
66
"""
77

8-
import asyncio
8+
import os
99
import logging
1010
import uuid
1111

@@ -17,12 +17,32 @@
1717
from archipy.adapters.base.sqlalchemy.session_manager_registry import SessionManagerRegistry
1818
from archipy.configs.base_config import BaseConfig
1919

20+
from features.test_containers import ContainerManager
21+
22+
from testcontainers.core.config import testcontainers_config
2023

2124
class TestConfig(BaseConfig):
2225
model_config = SettingsConfigDict(
2326
env_file=".env.test",
2427
)
2528

29+
# Test container images
30+
REDIS__IMAGE: str = "redis:7-alpine"
31+
POSTGRES__IMAGE: str = "postgres:17"
32+
ELASTIC__IMAGE: str = "elasticsearch:9.1.0"
33+
KAFKA__IMAGE: str = "confluentinc/cp-kafka:7.4.0"
34+
MINIO__IMAGE: str = "minio/minio:latest"
35+
KEYCLOAK__IMAGE: str = "quay.io/keycloak/keycloak:23.0"
36+
37+
def __init__(self, **kwargs):
38+
super().__init__(**kwargs)
39+
40+
# Configure testcontainers to use custom ryuk image
41+
ryuk_image = os.getenv("TESTCONTAINERS_RYUK_CONTAINER_IMAGE")
42+
if ryuk_image:
43+
testcontainers_config.ryuk_image = ryuk_image
44+
45+
2646

2747
# Initialize global config
2848
config = TestConfig()
@@ -43,6 +63,10 @@ def before_all(context: Context):
4363
# Create the scenario context pool manager
4464
context.scenario_context_pool = ScenarioContextPoolManager()
4565

66+
# Initialize and start all test containers
67+
context.test_containers = ContainerManager
68+
context.test_containers.start_all()
69+
4670

4771
def before_scenario(context: Context, scenario: Scenario):
4872
"""Setup performed before each scenario runs."""
@@ -62,6 +86,7 @@ def before_scenario(context: Context, scenario: Scenario):
6286
# Assign test config to scenario context
6387
try:
6488
scenario_context.store("test_config", config)
89+
scenario_context.store("test_containers", context.test_containers)
6590
except Exception as e:
6691
logger.exception(f"Error setting test config: {e}")
6792

@@ -85,6 +110,10 @@ def after_scenario(context: Context, scenario: Scenario):
85110

86111
def after_all(context: Context):
87112
"""Cleanup performed after all tests run."""
113+
# Stop all test containers
114+
if hasattr(context, "test_containers"):
115+
context.test_containers.stop_all()
116+
88117
# Clean up any remaining resources
89118
if hasattr(context, "scenario_context_pool"):
90119
context.scenario_context_pool.cleanup_all()

0 commit comments

Comments
 (0)