-
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(sentrykube): introduce additional possibilities to override config #63
base: main
Are you sure you want to change the base?
Changes from 15 commits
237b761
2d5eff4
1ad39eb
acdc150
8c1aecf
8292130
6581a8e
6404cca
4ae8efa
86ed1e8
b997eab
0718dbe
a470810
fb0bb07
3b9f8d7
ad9c539
832e046
1033493
06f43fc
f0b3551
1dea511
ac39e53
6b44492
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
from collections import OrderedDict | ||
from libsentrykube.config import Config | ||
from libsentrykube.customer import load_customer_data | ||
from libsentrykube.utils import workspace_root | ||
from libsentrykube.utils import workspace_root, deep_merge_dict | ||
|
||
_services = OrderedDict() | ||
|
||
|
@@ -100,9 +100,21 @@ def get_service_value_overrides( | |
external: bool = False, | ||
) -> dict: | ||
""" | ||
For the given service, return the values specified in the corresponding _values.yaml. | ||
Loads service configuration with regional and cluster-specific overrides. | ||
|
||
If "external=True" is specified, treat the service name as the full service path. | ||
This function implements a two-level configuration system where common regional settings | ||
can be shared across all clusters, with cluster-specific overrides on top. | ||
|
||
Directory Structure: | ||
region_overrides/ | ||
└── {region_name}/ | ||
├── _values.yaml # Common settings for all clusters in this region | ||
├── cluster1.yaml # Cluster-specific overrides | ||
└── cluster2.yaml # Cluster-specific overrides | ||
|
||
Override Precedence (highest to lowest): | ||
1. {cluster_name}.yaml # Cluster-specific settings | ||
2. _values.yaml # Common regional settings | ||
""" | ||
try: | ||
service_override_file = ( | ||
|
@@ -112,9 +124,109 @@ def get_service_value_overrides( | |
|
||
with open(service_override_file, "rb") as f: | ||
values = yaml.safe_load(f) | ||
|
||
# Try to load the config only after {cluster_name}.yaml was successfully loaded because the common override | ||
# only makes sense if there is a cluster config | ||
common_override_values = get_common_regional_override( | ||
service_name, region_name, external | ||
) | ||
|
||
if common_override_values: | ||
deep_merge_dict(common_override_values, values) | ||
return common_override_values | ||
|
||
return values | ||
except FileNotFoundError: | ||
values = {} | ||
return values | ||
return {} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Each of these methods ( Please do not merge different levels of overrides in the same method and create a new one instead. The merging should only happen in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the review, those are valid points. I will split it up and move the logic |
||
|
||
def get_common_regional_override( | ||
service_name: str, region_name: str, external: bool = False | ||
) -> dict: | ||
""" | ||
Helper function to load common regional configuration values. | ||
|
||
Looks for a '_values.yaml' file in the region's override directory that contains | ||
settings shared across all clusters in that region. | ||
""" | ||
try: | ||
common_service_override_file = ( | ||
get_service_value_override_path(service_name, region_name, external) | ||
/ "_values.yaml" | ||
) | ||
|
||
with open(common_service_override_file, "rb") as f: | ||
common_override_values = yaml.safe_load(f) | ||
|
||
return common_override_values | ||
except FileNotFoundError: | ||
return {} | ||
|
||
|
||
def get_hierarchical_value_overrides( | ||
service_name: str, | ||
region_name: str, | ||
cluster_name: str = "default", | ||
external: bool = False, | ||
) -> dict: | ||
""" | ||
Enables hierarchical configuration overrides with shared base values. | ||
|
||
This function extends the standard region_overrides system by adding support for | ||
shared base configurations. This helps reduce duplication across region-specific | ||
configurations. | ||
|
||
Directory Structure: | ||
region_overrides/ | ||
└── common_shared_config/ # Arbitrary name for the shared config group | ||
├── _values.yaml # Base values for this group | ||
└── {region_name}/ # Region-specific overrides | ||
└── {cluster_name}.yaml # Cluster-specific overrides | ||
Comment on lines
+191
to
+196
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure I follow the reasoning here.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes it's for single tenants. I agree that it's not great that the config diverges
Consider the following structure:
Additionally to reducing code duplication we would also see differences between customers more easily. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd be fine in having groups. Also please psot this PR in #team-sre-squad-monkeys as this will be an important change that impacts all services and those who manage all services may have opinions. |
||
|
||
Override Precedence (highest to lowest): | ||
1. region_name/cluster_name.yaml | ||
2. common_shared_config/_values.yaml | ||
3. Top-level configuration | ||
""" | ||
if external: | ||
service_regions_path = workspace_root() / service_name | ||
else: | ||
service_regions_path = get_service_path(service_name) | ||
|
||
service_regions_path = service_regions_path / "region_overrides" | ||
|
||
if not service_regions_path.exists(): | ||
return {} | ||
|
||
for override_group in service_regions_path.iterdir(): | ||
if not override_group.is_dir(): | ||
continue | ||
|
||
try: | ||
service_override_file = ( | ||
get_service_value_override_path( | ||
service_name, override_group.name, external | ||
) | ||
/ "_values.yaml" | ||
) | ||
|
||
with open(service_override_file, "rb") as f: | ||
base_values = yaml.safe_load(f) | ||
except FileNotFoundError: | ||
base_values = {} | ||
|
||
region_path = f"{override_group.name}/{region_name}" | ||
region_values = get_service_value_overrides( | ||
service_name, region_path, cluster_name, external | ||
) | ||
|
||
if not region_values: | ||
continue | ||
|
||
deep_merge_dict(base_values, region_values) | ||
return base_values | ||
|
||
return {} | ||
|
||
|
||
def get_tools_managed_service_value_overrides( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the order is right.
_values.yaml
file within a region (point 6) should be before point 2 (region override). If it is shaerd between clusetrs in the same region, the cluster specific file (these - https://github.com/getsentry/ops/tree/master/k8s/services/relay-pop/region_overrides/us) should be more specific than you point 6.In summary This should be the order from more generic to more specific
1 The per service value file (this is not region or cluster specific. It is service specific)
5 common override between subset of regions of the same service
6 common override between clusters in the same region (more specific than 5)
3 cluster specific override
4 managed override, which is basically equivalent to 3 but it is a separate file as it is managed by tools and cannot contain comments.
4 the cluster file is still there for historic reasons, but if you made changes to any of the above the cluster file is supposed to be empty for the specific service.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed comment. You're right that the order isn't correct, I misunderstood the existing comment and thought it's more of a "we have this kind of overrides" instead of them being the order from most to least specific. I will update it accordingly