Skip to content

Commit 8bf783e

Browse files
author
DeanLuus22021994
committed
refactor: reorganize Dapr components into subdirectories by type
HIGH PRIORITY openai#1 - File Structure Refactoring Complete Directory Structure: - bindings/http.yaml (was bindings-http.yaml) - configuration/default.yaml (was configuration.yaml) - pubsub/redis.yaml (was pubsub-redis.yaml) - secretstore/env.yaml (was secretstore-env.yaml) - statestore/default.yaml (was statestore.yaml) - statestore/postgres.yaml (was statestore-postgres.yaml) - statestore/redis.yaml (was statestore-redis.yaml) Rationale: - Groups files by component type following proper coding methodology - Removes redundant prefixes from filenames - Easier to add new components of same type - Improves maintainability and discoverability Testing: - Created tests/test_dapr_component_structure.py with TDD approach - Verified Dapr sidecar loads all 6 components from subdirectories - Dapr metadata endpoint confirms all components active: * statestore (default Redis) * statestore-redis * statestore-postgres * pubsub-redis * secretstore-env * http-binding No docker-compose.yml changes needed - Dapr recursively scans subdirectories.
1 parent a2e9034 commit 8bf783e

File tree

8 files changed

+185
-0
lines changed

8 files changed

+185
-0
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
"""Tests for Dapr component directory structure refactoring.
2+
3+
This module verifies that Dapr components can be organized in subdirectories
4+
by component type (statestore, pubsub, bindings, secretstore, configuration)
5+
and that Dapr runtime can correctly discover and load them.
6+
"""
7+
8+
import os
9+
from pathlib import Path
10+
from typing import Dict, List
11+
12+
import pytest
13+
import yaml
14+
15+
16+
@pytest.fixture
17+
def dapr_components_base_path() -> Path:
18+
"""Get the base path for Dapr components."""
19+
repo_root = Path(__file__).parent.parent
20+
return repo_root / ".devcontainer" / "dapr-components"
21+
22+
23+
@pytest.fixture
24+
def expected_component_structure() -> Dict[str, List[str]]:
25+
"""Define the expected directory structure for Dapr components.
26+
27+
Returns:
28+
Dictionary mapping subdirectory names to expected YAML files.
29+
"""
30+
return {
31+
"statestore": ["postgres.yaml", "redis.yaml", "default.yaml"],
32+
"pubsub": ["redis.yaml"],
33+
"bindings": ["http.yaml"],
34+
"secretstore": ["env.yaml"],
35+
"configuration": ["default.yaml"],
36+
}
37+
38+
39+
class TestDaprComponentDirectoryStructure:
40+
"""Test suite for Dapr component directory organization."""
41+
42+
def test_subdirectories_exist(
43+
self, dapr_components_base_path: Path, expected_component_structure: Dict[str, List[str]]
44+
):
45+
"""Verify all expected subdirectories exist."""
46+
for subdir in expected_component_structure.keys():
47+
subdir_path = dapr_components_base_path / subdir
48+
assert subdir_path.exists(), f"Subdirectory {subdir}/ should exist"
49+
assert subdir_path.is_dir(), f"{subdir}/ should be a directory"
50+
51+
def test_yaml_files_in_correct_locations(
52+
self, dapr_components_base_path: Path, expected_component_structure: Dict[str, List[str]]
53+
):
54+
"""Verify YAML files are in correct subdirectories with correct names."""
55+
for subdir, expected_files in expected_component_structure.items():
56+
subdir_path = dapr_components_base_path / subdir
57+
58+
for expected_file in expected_files:
59+
file_path = subdir_path / expected_file
60+
assert file_path.exists(), f"File {subdir}/{expected_file} should exist"
61+
assert file_path.is_file(), f"{subdir}/{expected_file} should be a file"
62+
assert file_path.suffix == ".yaml", f"{subdir}/{expected_file} should be a YAML file"
63+
64+
def test_no_prefixed_files_in_root(self, dapr_components_base_path: Path):
65+
"""Verify old prefixed files no longer exist in root directory."""
66+
old_files = [
67+
"statestore-postgres.yaml",
68+
"statestore-redis.yaml",
69+
"statestore.yaml",
70+
"pubsub-redis.yaml",
71+
"secretstore-env.yaml",
72+
"bindings-http.yaml",
73+
"configuration.yaml",
74+
]
75+
76+
for old_file in old_files:
77+
old_file_path = dapr_components_base_path / old_file
78+
assert not old_file_path.exists(), f"Old file {old_file} should not exist in root"
79+
80+
def test_yaml_files_are_valid(
81+
self, dapr_components_base_path: Path, expected_component_structure: Dict[str, List[str]]
82+
):
83+
"""Verify all YAML files have valid syntax and Dapr component structure."""
84+
for subdir, expected_files in expected_component_structure.items():
85+
subdir_path = dapr_components_base_path / subdir
86+
87+
for expected_file in expected_files:
88+
file_path = subdir_path / expected_file
89+
90+
with open(file_path, "r") as f:
91+
component = yaml.safe_load(f)
92+
93+
# Verify required Dapr component fields
94+
assert "apiVersion" in component, f"{subdir}/{expected_file} missing apiVersion"
95+
assert "kind" in component, f"{subdir}/{expected_file} missing kind"
96+
assert "metadata" in component, f"{subdir}/{expected_file} missing metadata"
97+
assert "spec" in component, f"{subdir}/{expected_file} missing spec"
98+
99+
assert component["apiVersion"] == "dapr.io/v1alpha1", f"{subdir}/{expected_file} wrong apiVersion"
100+
assert component["kind"] == "Component", f"{subdir}/{expected_file} should be Component kind"
101+
assert "name" in component["metadata"], f"{subdir}/{expected_file} missing component name"
102+
103+
def test_component_names_are_consistent(
104+
self, dapr_components_base_path: Path, expected_component_structure: Dict[str, List[str]]
105+
):
106+
"""Verify component names follow consistent naming conventions."""
107+
for subdir, expected_files in expected_component_structure.items():
108+
subdir_path = dapr_components_base_path / subdir
109+
110+
for expected_file in expected_files:
111+
file_path = subdir_path / expected_file
112+
113+
with open(file_path, "r") as f:
114+
component = yaml.safe_load(f)
115+
116+
component_name = component["metadata"]["name"]
117+
file_basename = expected_file.replace(".yaml", "")
118+
119+
# Component names should reflect their type and backend
120+
if file_basename == "default":
121+
# Default components use just the type name
122+
assert component_name in ["statestore", "configuration"], \
123+
f"Default component in {subdir}/ has unexpected name: {component_name}"
124+
else:
125+
# Named components should include backend identifier
126+
# e.g., statestore-postgres, statestore-redis, pubsub-redis
127+
assert subdir in component_name or file_basename in component_name, \
128+
f"Component name '{component_name}' should reference {subdir} or {file_basename}"
129+
130+
def test_statestore_components_have_correct_types(self, dapr_components_base_path: Path):
131+
"""Verify statestore components have correct Dapr state store types."""
132+
statestore_path = dapr_components_base_path / "statestore"
133+
134+
# postgres.yaml should use state.postgresql
135+
with open(statestore_path / "postgres.yaml", "r") as f:
136+
postgres = yaml.safe_load(f)
137+
assert postgres["spec"]["type"] == "state.postgresql", "postgres.yaml should use state.postgresql"
138+
139+
# redis.yaml and default.yaml should use state.redis
140+
with open(statestore_path / "redis.yaml", "r") as f:
141+
redis = yaml.safe_load(f)
142+
assert redis["spec"]["type"] == "state.redis", "redis.yaml should use state.redis"
143+
144+
with open(statestore_path / "default.yaml", "r") as f:
145+
default = yaml.safe_load(f)
146+
assert default["spec"]["type"] == "state.redis", "default.yaml should use state.redis"
147+
148+
def test_readme_exists_in_root(self, dapr_components_base_path: Path):
149+
"""Verify README.md still exists in root directory."""
150+
readme_path = dapr_components_base_path / "README.md"
151+
assert readme_path.exists(), "README.md should exist in dapr-components root"
152+
assert readme_path.is_file(), "README.md should be a file"
153+
154+
155+
class TestDaprComponentDiscovery:
156+
"""Test suite for Dapr runtime component discovery."""
157+
158+
def test_dapr_scans_subdirectories_recursively(self, dapr_components_base_path: Path):
159+
"""Verify Dapr components-path supports subdirectory scanning.
160+
161+
Note: This is a structural test. Runtime verification happens in
162+
test-docker-stack.ps1 by checking Dapr metadata endpoint.
163+
"""
164+
# Dapr runtime automatically scans subdirectories for component files
165+
# We verify the structure allows for this behavior
166+
167+
all_component_files = list(dapr_components_base_path.rglob("*.yaml"))
168+
169+
# Filter out README.md and only include YAML component files
170+
component_yamls = [
171+
f for f in all_component_files
172+
if f.is_file() and f.parent != dapr_components_base_path
173+
]
174+
175+
# Should have at least 7 component files in subdirectories
176+
assert len(component_yamls) >= 7, f"Expected at least 7 components in subdirectories, found {len(component_yamls)}"
177+
178+
# All component files should be in subdirectories, not root
179+
for component_file in component_yamls:
180+
assert component_file.parent != dapr_components_base_path, \
181+
f"Component {component_file.name} should be in a subdirectory"
182+
183+
184+
if __name__ == "__main__":
185+
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)