-
Notifications
You must be signed in to change notification settings - Fork 18
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: support for passing additional parameters from app repository to root repository using override file #184
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
|
@@ -59,6 +59,41 @@ config: | |
app-xy-test: | ||
``` | ||
|
||
## Passing additional custom keys from App Config to Root Config repositories | ||
|
||
``` | ||
Section to be discussed, proposal only. | ||
``` | ||
|
||
If App Team wants to pass additional parameters to the root repository - it may be done using additional custom_values.yaml located in the app_folder. Keys in this file will be validated against whitelist located in the root repository. | ||
If whitelist.yaml is missing - by default only key teamcode is allowed. | ||
|
||
### Files used during process | ||
|
||
**root_repo/whitelist.yaml** | ||
```yaml | ||
teamcode: null | ||
keyallowed: null | ||
``` | ||
**app_repo/app-xy-test/custom_values.yaml** | ||
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. maybe |
||
```yaml | ||
teamcode: team-xy | ||
keydisallowed: security-breach | ||
``` | ||
### Resulting file | ||
**root_repo/apps/team-a.yaml** | ||
```yaml | ||
repository: https://github.com/company-deployments/team-1-app-config-repo.git # link to your apps root repository | ||
|
||
# The applications that are synced by the `sync-app` command: | ||
applications: | ||
app-xy-production: # <- every entry corresponds to a directory in the apps root repository | ||
app-xy-staging: | ||
teamcode: team-xy | ||
app-xy-test: | ||
``` | ||
|
||
|
||
## Example | ||
|
||
```bash | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,12 @@ | ||
import logging | ||
import os | ||
from dataclasses import dataclass | ||
from typing import Any, Set, Tuple | ||
from typing import Any, Set, Tuple, Dict | ||
from gitopscli.git_api import GitApiConfig, GitRepo, GitRepoApiFactory | ||
from gitopscli.io_api.yaml_util import merge_yaml_element, yaml_file_load | ||
from gitopscli.io_api.yaml_util import YAMLException, merge_yaml_element, yaml_file_load, yaml_load | ||
from gitopscli.gitops_exception import GitOpsException | ||
from .command import Command | ||
|
||
|
||
class SyncAppsCommand(Command): | ||
@dataclass(frozen=True) | ||
class Args(GitApiConfig): | ||
|
@@ -50,18 +49,65 @@ def __sync_apps(team_config_git_repo: GitRepo, root_config_git_repo: GitRepo, gi | |
apps_from_other_repos, | ||
found_apps_path, | ||
) = __find_apps_config_from_repo(team_config_git_repo, root_config_git_repo) | ||
|
||
if current_repo_apps == repo_apps: | ||
logging.info("Root repository already up-to-date. I'm done here.") | ||
return | ||
|
||
# TODO to be discussed - how to proceed with changes here, as adding additional custom_values will invalidate this check. | ||
# Based on the outcome - test test_sync_apps_already_up_to_date also needs to be modified. | ||
# Options: | ||
# - remove this check | ||
# - add validation of customizationfile presence to __find_apps_config_from_repo | ||
# - move and modify this check to validate actual changes (get the applications list from resulting yaml and compare with current one) | ||
# if current_repo_apps == repo_apps: | ||
# logging.info("Root repository already up-to-date. I'm done here.") | ||
# return | ||
|
||
__check_if_app_already_exists(repo_apps, apps_from_other_repos) | ||
|
||
logging.info("Sync applications in root repository's %s.", apps_config_file_name) | ||
merge_yaml_element(apps_config_file, found_apps_path, {repo_app: {} for repo_app in repo_apps}) | ||
|
||
merge_yaml_element( | ||
apps_config_file, | ||
found_apps_path, | ||
{repo_app: __clean_repo_app(root_config_git_repo, team_config_git_repo, repo_app) for repo_app in repo_apps}, | ||
) | ||
__commit_and_push(team_config_git_repo, root_config_git_repo, git_user, git_email, apps_config_file_name) | ||
|
||
|
||
def __clean_yaml(values: Dict[str, Any], whitelist: Dict[str, Any], app_name: str) -> Any: | ||
|
||
whitelisted_yml = {k:v for k,v in values.items() if k in whitelist.keys()} | ||
missing = set(values).difference(whitelisted_yml) | ||
logging.info("Keys removed from %s custom_values.yaml %s", app_name, missing) | ||
return whitelisted_yml | ||
|
||
|
||
def __clean_repo_app(root_config_git_repo: GitRepo, team_config_git_repo: GitRepo, app_name: str) -> Any: | ||
app_spec_file = team_config_git_repo.get_full_file_path(f"{app_name}/custom_values.yaml") | ||
app_spec_whitelist_file = root_config_git_repo.get_full_file_path(f"whitelist.yaml") | ||
try: | ||
app_config_content = yaml_file_load(app_spec_file) | ||
except FileNotFoundError as ex: | ||
logging.warning("no specific app settings file found for %s", app_name) | ||
return {} | ||
except YAMLException as yex: | ||
logging.error("Unable to load %s/custom_values.yaml from app repository, please validate if this is a correct YAML file" , exc_info=yex) | ||
return {} | ||
#TODO: should sync fail or skip adding custom values (return {}) | ||
#TODO: which errors should be raised as GitOpsException | ||
try: | ||
whitelist_config_content = yaml_file_load(app_spec_whitelist_file) | ||
except FileNotFoundError as ex: | ||
logging.warning("no whitelist app settings file found in root repo, by default allowing teamcode only") | ||
whitelist_yaml_string = """\ | ||
teamcode: null | ||
""" | ||
whitelist_config_content = yaml_load(whitelist_yaml_string) | ||
except YAMLException as yex: | ||
logging.error("Unable to load whitelist.yaml from root repository, please validate if this is a correct YAML file" , exc_info=yex) | ||
return {} | ||
#TODO: should sync fail, assume default whitelist or skip adding custom 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. Taking into account that the sync-apps command is usually run by some pipeline not directly maintained by the individual teams, it might be a bit hard to figure out what went wrong (or even notice that it failed in the first place). A compromise could be to create a YAML comment in the resulting root config file with the failure message: applications:
app-xy-staging:
teamcode: team-xy
# sync-apps error: 'keydisallowed' not allowed (custom_values.yaml, line 3) This way you neither have to swallow the error nor break the sync. |
||
return __clean_yaml(app_config_content, whitelist_config_content, app_name) | ||
|
||
|
||
def __find_apps_config_from_repo( | ||
team_config_git_repo: GitRepo, root_config_git_repo: GitRepo | ||
) -> Tuple[str, str, Set[str], Set[str], str]: | ||
|
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.
why not a list of allowed keys?