diff --git a/make_argocd_fly/application.py b/make_argocd_fly/application.py index 060d3c7..1e1507b 100644 --- a/make_argocd_fly/application.py +++ b/make_argocd_fly/application.py @@ -6,7 +6,7 @@ from make_argocd_fly.resource import ResourceViewer, ResourceWriter from make_argocd_fly.renderer import JinjaRenderer -from make_argocd_fly.utils import multi_resource_parser, merge_dicts, generate_filename +from make_argocd_fly.utils import multi_resource_parser, resource_parser, merge_dicts, generate_filename from make_argocd_fly.config import get_config log = logging.getLogger(__name__) @@ -170,9 +170,17 @@ async def prepare(self) -> str: log.error('Error rendering template {}: {}'.format(yml_child.element_rel_path, e)) raise - for resource_kind, resource_name, resource_yml in multi_resource_parser(content): - file_path = os.path.join(self.env_name, os.path.dirname(yml_child.element_rel_path), generate_filename(resource_kind, resource_name)) - tmp_resource_writer.store_resource(file_path, resource_yml) + # TODO: (None, None) is not a good way to check if the content is a k8s resource + if resource_parser(content) != (None, None): + for resource_kind, resource_name, resource_yml in multi_resource_parser(content): + file_path = os.path.join(self.env_name, os.path.dirname(yml_child.element_rel_path), generate_filename([resource_kind, resource_name])) + tmp_resource_writer.store_resource(file_path, resource_yml) + else: + file_path = os.path.join( + self.env_name, os.path.dirname(yml_child.element_rel_path), + generate_filename([os.path.basename(yml_child.element_rel_path.split('.')[0])]) + ) + tmp_resource_writer.store_resource(file_path, content) await tmp_resource_writer.write_resources() diff --git a/make_argocd_fly/main.py b/make_argocd_fly/main.py index 3406f8f..9e78ffe 100644 --- a/make_argocd_fly/main.py +++ b/make_argocd_fly/main.py @@ -73,7 +73,7 @@ async def generate(render_envs, render_apps) -> None: output_writer = ResourceWriter(config.get_output_dir()) for app in apps: for resource_kind, resource_name, resource_yml in multi_resource_parser(app.resources): - file_path = os.path.join(app.get_app_rel_path(), generate_filename(resource_kind, resource_name)) + file_path = os.path.join(app.get_app_rel_path(), generate_filename([resource_kind, resource_name])) output_writer.store_resource(file_path, resource_yml) if apps: diff --git a/make_argocd_fly/utils.py b/make_argocd_fly/utils.py index 9a47e1d..0fd1afc 100644 --- a/make_argocd_fly/utils.py +++ b/make_argocd_fly/utils.py @@ -13,11 +13,12 @@ def resource_parser(resource_yml: str) -> tuple[str, str]: if match: resource_kind = match.group(2).strip() - match = re.search(r'(^metadata:|\nmetadata:).*', resource_yml) - if match: - match = re.search(r'(^\s\sname:|\n\s\sname:)(.+)', resource_yml[match.start():]) + if resource_kind: + match = re.search(r'(^metadata:|\nmetadata:).*', resource_yml) if match: - resource_name = match.group(2).strip() + match = re.search(r'(^\s\sname:|\n\s\sname:)(.+)', resource_yml[match.start():]) + if match: + resource_name = match.group(2).strip() return (resource_kind, resource_name) @@ -31,16 +32,12 @@ def multi_resource_parser(multi_resource_yml: str) -> tuple[str, str, str]: yield (resource_kind, resource_name, resource_yml) -def generate_filename(resource_kind: str, resource_name: str) -> str: - if not resource_kind: - log.error('Parameter `resource_kind` is undefined') +def generate_filename(filename_parts: list) -> str: + if not filename_parts: + log.error('Filename cannot be constructed') raise Exception - if resource_name: - return '{}_{}.yml'.format(resource_kind, resource_name) - else: - # kustomize expects one of the following files to be present: 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' - return '{}.yml'.format(resource_kind).lower() + return '_'.join([filename_part for filename_part in filename_parts if filename_part]).lower() + '.yml' def merge_dicts(*dicts): diff --git a/tests/manual/config.yml b/tests/manual/config.yml index 0bc4707..73fa941 100644 --- a/tests/manual/config.yml +++ b/tests/manual/config.yml @@ -16,6 +16,7 @@ vars: - resources-finalizer.argocd.argoproj.io namespace: kube-system version: 0.1.0 + # reference_version: '["vars"]["version"]' app: resource: Deployment_thanos.yml json_var: json @@ -60,6 +61,7 @@ envs: subdirectory_2/app_8: {app_deployer: service_deployer, project: management, destination_namespace: kube-default} app_9: {app_deployer: service_deployer, project: management, destination_namespace: kube-default} app_10: {app_deployer: service_deployer, project: management, destination_namespace: kube-default} + app_11: {app_deployer: service_deployer, project: management, destination_namespace: kube-default} vars: argocd: api_server: management-api-server diff --git a/tests/manual/output/management/app_11/deployment_hello-world.yml b/tests/manual/output/management/app_11/deployment_hello-world.yml new file mode 100644 index 0000000..5c41706 --- /dev/null +++ b/tests/manual/output/management/app_11/deployment_hello-world.yml @@ -0,0 +1,40 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: hello-world + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: hello-world + app.kubernetes.io/version: 1.16.0 + helm.sh/chart: hello-world-0.1.0 + name: hello-world +spec: + replicas: 2 + selector: + matchLabels: + app.kubernetes.io/instance: hello-world + app.kubernetes.io/name: hello-world + template: + metadata: + labels: + app.kubernetes.io/instance: hello-world + app.kubernetes.io/name: hello-world + spec: + containers: + - image: nginx:1.16.0 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: / + port: http + name: hello-world + ports: + - containerPort: 80 + name: http + protocol: TCP + readinessProbe: + httpGet: + path: / + port: http + serviceAccountName: hello-world diff --git a/tests/manual/output/management/app_11/service_hello-world.yml b/tests/manual/output/management/app_11/service_hello-world.yml new file mode 100644 index 0000000..d3a98ba --- /dev/null +++ b/tests/manual/output/management/app_11/service_hello-world.yml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: hello-world + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: hello-world + app.kubernetes.io/version: 1.16.0 + helm.sh/chart: hello-world-0.1.0 + name: hello-world +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/instance: hello-world + app.kubernetes.io/name: hello-world + type: ClusterIP diff --git a/tests/manual/output/management/app_11/serviceaccount_hello-world.yml b/tests/manual/output/management/app_11/serviceaccount_hello-world.yml new file mode 100644 index 0000000..4de9d2c --- /dev/null +++ b/tests/manual/output/management/app_11/serviceaccount_hello-world.yml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: hello-world + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: hello-world + app.kubernetes.io/version: 1.16.0 + helm.sh/chart: hello-world-0.1.0 + name: hello-world diff --git a/tests/manual/output/management/service_deployer/Application_app-11-management.yml b/tests/manual/output/management/service_deployer/Application_app-11-management.yml new file mode 100644 index 0000000..30cc21e --- /dev/null +++ b/tests/manual/output/management/service_deployer/Application_app-11-management.yml @@ -0,0 +1,20 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: app-11-management + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: management + source: + repoURL: url + targetRevision: revision + path: output/management/app_11 + destination: + server: management-api-server + namespace: kube-default + syncPolicy: + syncOptions: + - ServerSideApply=true diff --git a/tests/manual/source/app_11/kustomization.yml.j2 b/tests/manual/source/app_11/kustomization.yml.j2 new file mode 100644 index 0000000..8f63073 --- /dev/null +++ b/tests/manual/source/app_11/kustomization.yml.j2 @@ -0,0 +1,11 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +helmCharts: + - name: hello-world + namespace: {{ namespace }} + releaseName: hello-world + repo: https://helm.github.io/examples + version: {{ version }} + valuesFile: values.yml diff --git a/tests/manual/source/app_11/values.yml.j2 b/tests/manual/source/app_11/values.yml.j2 new file mode 100644 index 0000000..5ef7832 --- /dev/null +++ b/tests/manual/source/app_11/values.yml.j2 @@ -0,0 +1 @@ +replicaCount: 2 diff --git a/tests/test_utils.py b/tests/test_utils.py index 6cad6f1..35edfa5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -284,20 +284,25 @@ def test_multi_resource_parser_with_valid_yaml_not_an_extra_separator_2(): ### generate_filename ##################### -def test_generate_filename_undefined_resource_kind(tmp_path, caplog): +def test_generate_filename_undefined_parts(caplog): with pytest.raises(Exception): - generate_filename(None, 'key_1') - assert 'Parameter `resource_kind` is undefined' in caplog.text + generate_filename([]) + assert 'Filename cannot be constructed' in caplog.text with pytest.raises(Exception): - generate_filename('', 'key_1') - assert 'Parameter `resource_kind` is undefined' in caplog.text + generate_filename(None) + assert 'Filename cannot be constructed' in caplog.text + +def test_generate_filename_undefined_first_elements(caplog): + assert generate_filename([None, 'key_1']) == 'key_1.yml' + + assert generate_filename(['', 'key_1']) == 'key_1.yml' def test_generate_filename(tmp_path): - assert generate_filename('key_1', 'key_2') == 'key_1_key_2.yml' + assert generate_filename(['key_1', 'key_2']) == 'key_1_key_2.yml' -def test_generate_filename_undefined_resource_name(tmp_path): - assert generate_filename('key_1', None) == 'key_1.yml' +def test_generate_filename_undefined_end_element(tmp_path): + assert generate_filename(['key_1', None]) == 'key_1.yml' ############### ### merge_dicts