Skip to content

Commit f109741

Browse files
authored
Merge pull request #26 from Zipstack/feature/set-value-command
Implement set-value command
2 parents 6e170db + bb47cf0 commit f109741

File tree

7 files changed

+525
-10
lines changed

7 files changed

+525
-10
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Standardize Terminology: Environment to Deployment
2+
3+
This document outlines the tasks required to standardize the terminology in the codebase, replacing all instances of "environment" with "deployment" for consistency.
4+
5+
## Background
6+
7+
Currently, the codebase uses "environment" in the internal API and "deployment" in the CLI interface and user-facing messages. This inconsistency can lead to confusion for developers and users. The goal is to standardize on "deployment" throughout the codebase.
8+
9+
## Tasks
10+
11+
### 1. Update Core Models
12+
13+
- [ ] Update `HelmValuesConfig` class:
14+
- [ ] Change method signatures to use "deployment" instead of "environment"
15+
- [ ] Update docstrings and comments
16+
- [ ] Ensure backward compatibility or provide migration path
17+
18+
- [ ] Update `Value` class:
19+
- [ ] Rename `environment` parameter to `deployment` in constructor and methods
20+
- [ ] Update docstrings and comments
21+
22+
### 2. Update Command Classes
23+
24+
- [ ] Update `SetValueCommand` class:
25+
- [ ] Rename internal variables from "environment" to "deployment"
26+
- [ ] Ensure all docstrings and comments use "deployment"
27+
28+
- [ ] Review and update other command classes that might use "environment"
29+
30+
### 3. Update Backend Classes
31+
32+
- [ ] Update `SimpleValueBackend` class:
33+
- [ ] Rename method parameters from "environment" to "deployment"
34+
- [ ] Update internal storage keys if necessary
35+
36+
- [ ] Update other backend implementations if present
37+
38+
### 4. Update Tests
39+
40+
- [ ] Update unit tests:
41+
- [ ] Rename test variables from "environment" to "deployment"
42+
- [ ] Update mock objects and assertions
43+
44+
- [ ] Update integration tests:
45+
- [ ] Ensure all tests use "deployment" consistently
46+
47+
### 5. Update Documentation
48+
49+
- [ ] Update design documentation:
50+
- [ ] Review and update low-level-design.md
51+
- [ ] Review and update sequence-diagrams.md
52+
53+
- [ ] Update user documentation:
54+
- [ ] Ensure all examples and explanations use "deployment"
55+
56+
### 6. Create Migration Plan
57+
58+
- [ ] Assess impact on existing configurations:
59+
- [ ] Determine if existing configurations need to be migrated
60+
- [ ] Create migration script if necessary
61+
62+
## Implementation Strategy
63+
64+
This change should be implemented as a single, focused PR to ensure consistency across the codebase. The PR should:
65+
66+
1. Not include any functional changes beyond the terminology standardization
67+
2. Include comprehensive tests to ensure no functionality is broken
68+
3. Update all relevant documentation
69+
70+
## Testing Strategy
71+
72+
1. Run all existing tests to ensure they pass with the updated terminology
73+
2. Add specific tests to verify that the terminology change doesn't affect functionality
74+
3. Manually test key workflows to ensure they work as expected
75+
76+
## Risks and Mitigation
77+
78+
- **Breaking Changes**: This change may introduce breaking changes for users who have integrated with the internal API. Consider providing a deprecation period or backward compatibility layer.
79+
- **Documentation**: Ensure all documentation is updated to reflect the new terminology to avoid confusion.

docs/Development/tasks.md

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,21 @@
9393
- [x] Add basic path validation
9494
- [x] Add metadata validation
9595
- [x] Add config update
96-
- [ ] Implement add-deployment command
97-
- [ ] Add basic deployment validation
98-
- [ ] Add backend validation
99-
- [ ] Add deployment registration
96+
- [x] Implement add-deployment command
97+
- [x] Add basic deployment validation
98+
- [x] Add backend validation
99+
- [x] Add deployment registration
100100
- [ ] Implement generate command
101101
- [ ] Add template generation
102102
- [ ] Add basic value substitution
103103

104104
- [ ] Value Management Commands
105-
- [ ] Implement get-value command
106-
- [ ] Add basic path validation
107-
- [ ] Add value retrieval
108-
- [ ] Implement set-value command
109-
- [ ] Add basic path validation
110-
- [ ] Add value storage
105+
- [x] Implement set-value command
106+
- [x] Add basic path validation
107+
- [x] Add value storage
108+
- [ ] Implement generate command
109+
- [ ] Add template generation
110+
- [ ] Add basic value substitution
111111

112112
#### Phase 2: Enhanced Safety & Management
113113
- [x] Enhanced Command Infrastructure
@@ -123,6 +123,11 @@
123123
- [ ] Add conflict detection
124124
- [ ] Add dependency validation
125125

126+
- [ ] Value Management Commands
127+
- [ ] Implement get-value command
128+
- [ ] Add basic path validation
129+
- [ ] Add value retrieval
130+
126131
- [ ] Basic Validation System
127132
- [ ] Add PathValidator class
128133
- [ ] Add path format validation
@@ -259,6 +264,16 @@
259264
- [ ] Add missing tests
260265
- [ ] Improve existing tests
261266

267+
## Code Quality and Maintenance
268+
- [ ] Standardize terminology (environment → deployment)
269+
- [ ] Update core models (HelmValuesConfig, Value)
270+
- [ ] Update command classes
271+
- [ ] Update backend classes
272+
- [ ] Update tests
273+
- [ ] Update documentation
274+
- [ ] Add more comprehensive error handling
275+
- [ ] Improve test coverage
276+
262277
## Development Guidelines
263278
1. Follow TDD approach
264279
- Write tests first

helm_values_manager/cli.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from helm_values_manager.commands.add_deployment_command import AddDeploymentCommand
88
from helm_values_manager.commands.add_value_config_command import AddValueConfigCommand
99
from helm_values_manager.commands.init_command import InitCommand
10+
from helm_values_manager.commands.set_value_command import SetValueCommand
1011
from helm_values_manager.utils.logger import HelmLogger
1112

1213
COMMAND_INFO = "helm values-manager"
@@ -97,5 +98,31 @@ def add_deployment(
9798
raise typer.Exit(code=1) from e
9899

99100

101+
@app.command("set-value")
102+
def set_value(
103+
path: str = typer.Option(..., "--path", "-p", help="Configuration path (e.g., 'app.replicas')"),
104+
deployment: str = typer.Option(
105+
..., "--deployment", "-d", help="Deployment to set the value for (e.g., 'dev', 'prod')"
106+
),
107+
value: str = typer.Option(..., "--value", "-v", help="Value to set"),
108+
):
109+
"""Set a value for a specific path and deployment."""
110+
try:
111+
command = SetValueCommand()
112+
113+
# Create kwargs for command execution
114+
kwargs = {
115+
"path": path,
116+
"environment": deployment, # Map deployment to environment for API compatibility
117+
"value": value,
118+
}
119+
120+
result = command.execute(**kwargs)
121+
typer.echo(result)
122+
except Exception as e:
123+
HelmLogger.error("Failed to set value: %s", str(e))
124+
raise typer.Exit(code=1) from e
125+
126+
100127
if __name__ == "__main__":
101128
app(prog_name=COMMAND_INFO)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""Command to set a value for a specific path and deployment."""
2+
3+
from typing import Optional
4+
5+
from helm_values_manager.commands.base_command import BaseCommand
6+
from helm_values_manager.models.helm_values_config import HelmValuesConfig
7+
from helm_values_manager.utils.logger import HelmLogger
8+
9+
10+
class SetValueCommand(BaseCommand):
11+
"""Command to set a value for a specific path and deployment."""
12+
13+
def run(self, config: Optional[HelmValuesConfig] = None, **kwargs) -> str:
14+
"""
15+
Set a value for a specific path and deployment.
16+
17+
Args:
18+
config: The loaded configuration
19+
**kwargs: Command arguments
20+
- path (str): The configuration path (e.g., 'app.replicas')
21+
- environment (str): The deployment to set the value for (e.g., 'dev', 'prod')
22+
- value (str): The value to set
23+
24+
Returns:
25+
str: Success message
26+
27+
Raises:
28+
ValueError: If path or environment is empty
29+
KeyError: If path or deployment doesn't exist in the configuration
30+
"""
31+
if config is None:
32+
raise ValueError("Configuration not loaded")
33+
34+
path = kwargs.get("path")
35+
if not path:
36+
raise ValueError("Path cannot be empty")
37+
38+
environment = kwargs.get("environment")
39+
if not environment:
40+
raise ValueError("Deployment cannot be empty")
41+
42+
value = kwargs.get("value")
43+
44+
# Validate that the deployment exists
45+
if environment not in config.deployments:
46+
raise KeyError(f"Deployment '{environment}' not found")
47+
48+
try:
49+
# Set the value for the specified path and deployment
50+
config.set_value(path=path, environment=environment, value=value)
51+
52+
# Save the updated configuration
53+
self.save_config(config)
54+
55+
HelmLogger.debug("Set value for path '%s' in deployment '%s'", path, environment)
56+
return f"Successfully set value for path '{path}' in deployment '{environment}'"
57+
except KeyError as e:
58+
HelmLogger.error("Failed to set value: %s", str(e))
59+
raise
60+
except Exception as e:
61+
HelmLogger.error("Failed to set value: %s", str(e))
62+
raise

tests/integration/test_cli_integration.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,117 @@ def test_add_deployment_no_config(plugin_install, tmp_path):
261261
stdout, stderr, returncode = run_helm_command(["values-manager", "add-deployment", "dev"])
262262
assert returncode == 1
263263
assert "Configuration file helm-values.json not found" in stderr
264+
265+
266+
def test_set_value_command(plugin_install, tmp_path):
267+
"""Test that the set-value command works correctly."""
268+
# Create a working directory
269+
work_dir = tmp_path / "test_set_value"
270+
work_dir.mkdir()
271+
os.chdir(work_dir)
272+
273+
# Initialize the config
274+
init_stdout, init_stderr, init_returncode = run_helm_command(
275+
["values-manager", "init", "--release", "test-release"]
276+
)
277+
assert init_returncode == 0
278+
assert Path("helm-values.json").exists()
279+
280+
# Add a deployment
281+
add_deployment_stdout, add_deployment_stderr, add_deployment_returncode = run_helm_command(
282+
["values-manager", "add-deployment", "dev"]
283+
)
284+
assert add_deployment_returncode == 0
285+
286+
# Add a value config
287+
add_value_config_stdout, add_value_config_stderr, add_value_config_returncode = run_helm_command(
288+
[
289+
"values-manager",
290+
"add-value-config",
291+
"--path",
292+
"app.replicas",
293+
"--description",
294+
"Number of replicas",
295+
"--required",
296+
]
297+
)
298+
assert add_value_config_returncode == 0
299+
300+
# Set a value
301+
stdout, stderr, returncode = run_helm_command(
302+
["values-manager", "set-value", "--path", "app.replicas", "--deployment", "dev", "--value", "3"]
303+
)
304+
assert returncode == 0
305+
assert "Successfully set value for path 'app.replicas' in deployment 'dev'" in stdout
306+
307+
# Verify the value was set
308+
with open("helm-values.json", "r") as f:
309+
config = json.load(f)
310+
311+
# The value itself is stored in the backend, not directly in the config file
312+
# But we can verify that the path exists in the config
313+
assert any(path["path"] == "app.replicas" for path in config["config"])
314+
315+
316+
def test_set_value_nonexistent_path(plugin_install, tmp_path):
317+
"""Test that setting a value for a nonexistent path fails with the correct error message."""
318+
# Create a working directory
319+
work_dir = tmp_path / "test_set_value_nonexistent_path"
320+
work_dir.mkdir()
321+
os.chdir(work_dir)
322+
323+
# Initialize the config
324+
init_stdout, init_stderr, init_returncode = run_helm_command(
325+
["values-manager", "init", "--release", "test-release"]
326+
)
327+
assert init_returncode == 0
328+
assert Path("helm-values.json").exists()
329+
330+
# Add a deployment
331+
add_deployment_stdout, add_deployment_stderr, add_deployment_returncode = run_helm_command(
332+
["values-manager", "add-deployment", "dev"]
333+
)
334+
assert add_deployment_returncode == 0
335+
336+
# Try to set a value for a nonexistent path
337+
stdout, stderr, returncode = run_helm_command(
338+
["values-manager", "set-value", "--path", "nonexistent.path", "--deployment", "dev", "--value", "3"]
339+
)
340+
assert returncode == 1
341+
assert "Path nonexistent.path not found" in stderr
342+
343+
344+
def test_set_value_nonexistent_deployment(plugin_install, tmp_path):
345+
"""Test that setting a value for a nonexistent deployment fails with the correct error message."""
346+
# Create a working directory
347+
work_dir = tmp_path / "test_set_value_nonexistent_deployment"
348+
work_dir.mkdir()
349+
os.chdir(work_dir)
350+
351+
# Initialize the config
352+
init_stdout, init_stderr, init_returncode = run_helm_command(
353+
["values-manager", "init", "--release", "test-release"]
354+
)
355+
assert init_returncode == 0
356+
assert Path("helm-values.json").exists()
357+
358+
# Add a value config
359+
add_value_config_stdout, add_value_config_stderr, add_value_config_returncode = run_helm_command(
360+
[
361+
"values-manager",
362+
"add-value-config",
363+
"--path",
364+
"app.replicas",
365+
"--description",
366+
"Number of replicas",
367+
"--required",
368+
]
369+
)
370+
assert add_value_config_returncode == 0
371+
372+
# Try to set a value for a nonexistent deployment
373+
stdout, stderr, returncode = run_helm_command(
374+
["values-manager", "set-value", "--path", "app.replicas", "--deployment", "nonexistent", "--value", "3"]
375+
)
376+
assert returncode == 1
377+
assert "Deployment 'nonexistent' not found" in stderr

0 commit comments

Comments
 (0)