content: #  Copyright (c) ZenML GmbH 2025. All Rights Reserved.
  #
  #  Licensed under the Apache License, Version 2.0 (the "License");
  #  you may not use this file except in compliance with the License.
  #  You may obtain a copy of the License at:
  #
  #       https://www.apache.org/licenses/LICENSE-2.0
  #
  #  Unless required by applicable law or agreed to in writing, software
  #  distributed under the License is distributed on an "AS IS" BASIS,
  #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  #  OR implied. See the License for the specific language governing
  #  permissions and limitations under the License.
  
  import textwrap
  
  import pytest
  import yaml
  
  from zenml.integrations.kubernetes.template_engine import (
      KubernetesTemplateEngine,
  )
  
  # ---------------------------------------------------------------------------
  # load_yaml_documents
  # ---------------------------------------------------------------------------
  
  
  def test_load_yaml_documents_multi_doc():
      """Loading multiple YAML documents separated by --- yields multiple dicts."""
      yaml_content = """
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: cm1
      ---
      apiVersion: v1
      kind: Secret
      metadata:
        name: s1
      """
      docs = KubernetesTemplateEngine.load_yaml_documents(
          textwrap.dedent(yaml_content)
      )
      assert len(docs) == 2
      assert {d["metadata"]["name"] for d in docs} == {"cm1", "s1"}
  
  
  def test_load_yaml_documents_list_format():
      """Top-level list of resources is supported and flattened."""
      yaml_content = """
      - apiVersion: v1
        kind: ConfigMap
        metadata:
          name: cm1
      - apiVersion: v1
        kind: Secret
        metadata:
          name: s1
      """
      docs = KubernetesTemplateEngine.load_yaml_documents(
          textwrap.dedent(yaml_content)
      )
      assert len(docs) == 2
      assert {d["metadata"]["name"] for d in docs} == {"cm1", "s1"}
  
  
  def test_load_yaml_documents_empty_returns_empty_list():
      """Empty or whitespace-only YAML returns an empty list (no docs)."""
      for yaml_content in ("", "   ", "\n# just comment\n"):
          docs = KubernetesTemplateEngine.load_yaml_documents(yaml_content)
          assert docs == []
  
  
  def test_load_yaml_documents_single_resource():
      """Single YAML resource (no list, no ---) is supported."""
      yaml_content = """
      apiVersion: v1
      kind: Service
      metadata:
        name: my-svc
      """
      docs = KubernetesTemplateEngine.load_yaml_documents(
          textwrap.dedent(yaml_content)
      )
      assert len(docs) == 1
      assert docs[0]["kind"] == "Service"
      assert docs[0]["metadata"]["name"] == "my-svc"
  
  
  def test_load_yaml_documents_invalid_yaml_raises_value_error():
      """Invalid YAML should be turned into a ValueError."""
      yaml_content = "apiVersion: v1\nkind: ConfigMap\nmetadata: [unclosed"
      with pytest.raises(ValueError, match="Invalid YAML"):
          KubernetesTemplateEngine.load_yaml_documents(yaml_content)
  
  
  def test_load_yaml_documents_non_dict_or_list_doc_raises():
      """YAML docs that are not dict or list of dicts are rejected."""
      yaml_content = """
      42
      """
      with pytest.raises(ValueError, match="must be a dictionary or list"):
          KubernetesTemplateEngine.load_yaml_documents(
              textwrap.dedent(yaml_content)
          )
  
  
  def test_load_yaml_documents_list_with_non_dict_item_raises():
      """List docs must contain only dict items."""
      yaml_content = """
      - apiVersion: v1
        kind: ConfigMap
        metadata:
          name: cm1
      - 42
      """
      with pytest.raises(ValueError, match=r"item 2 must be a dictionary"):
          KubernetesTemplateEngine.load_yaml_documents(
              textwrap.dedent(yaml_content)
          )
  
  
  # ---------------------------------------------------------------------------
  # render_template
  # ---------------------------------------------------------------------------
  
  
  def test_render_template_with_templating(tmp_path):
      yaml_file = tmp_path / "svc.yaml"
      yaml_file.write_text(
          textwrap.dedent(
              """\
              apiVersion: v1
              kind: Service
              metadata:
                name: {{ name }}
              spec:
                type: ClusterIP
                ports:
                  - port: {{ port }}
              """
          )
      )
  
      eng = KubernetesTemplateEngine(strict_undefined=True)
      resources = eng.render_template(
          str(yaml_file),
          context={"name": "my-svc", "port": 8080},
      )
  
      assert len(resources) == 1
      svc = resources[0]
      assert svc["kind"] == "Service"
      assert svc["metadata"]["name"] == "my-svc"
      assert svc["spec"]["ports"][0]["port"] == 8080
  
  
  def test_render_template_strict_undefined_raises_for_missing_variable(
      tmp_path,
  ):
      yaml_file = tmp_path / "cm.yaml"
      yaml_file.write_text(
          textwrap.dedent(
              """\
              apiVersion: v1
              kind: ConfigMap
              metadata:
                name: {{ cm_name }}
              data:
                key: value
              """
          )
      )
  
      eng = KubernetesTemplateEngine(strict_undefined=True)
  
      with pytest.raises(ValueError, match="Failed to render Jinja2 template"):
          eng.render_template(str(yaml_file), context={})  # cm_name missing
  
  
  def test_render_template_non_strict_undefined_renders_blank_for_missing_variable(
      tmp_path,
  ):
      yaml_file = tmp_path / "cm.yaml"
      yaml_file.write_text(
          textwrap.dedent(
              """\
              apiVersion: v1
              kind: ConfigMap
              metadata:
                name: {{ cm_name }}
              """
          )
      )
  
      eng = KubernetesTemplateEngine(strict_undefined=False)
      resources = eng.render_template(str(yaml_file), context={})
      assert len(resources) == 1
      cm = resources[0]
      assert cm["metadata"]["name"] in ("", None)
  
  
  def test_render_template_invalid_yaml_after_rendering_raises(tmp_path):
      """Ensure YAML parsing errors after successful Jinja rendering get wrapped."""
      yaml_file = tmp_path / "bad.yaml"
      yaml_file.write_text(
          textwrap.dedent(
              """\
              apiVersion: v1
              kind: ConfigMap
              metadata:
                name: {{ name }}
              data:
                key: [unclosed
              """
          )
      )
  
      eng = KubernetesTemplateEngine(strict_undefined=True)
      with pytest.raises(ValueError, match="Invalid YAML"):
          eng.render_template(str(yaml_file), context={"name": "cm"})
  
  
  def test_render_template_round_trips_to_yaml_and_back(tmp_path):
      """Sanity check that our to_yaml filter emits valid YAML."""
      yaml_file = tmp_path / "obj.yaml"
      yaml_file.write_text(
          textwrap.dedent(
              """\
              apiVersion: v1
              kind: ConfigMap
              metadata:
                name: cm
              data:
                as_yaml: |
                  {{ data | to_yaml }}
              """
          )
      )
  
      eng = KubernetesTemplateEngine(strict_undefined=True)
      resources = eng.render_template(
          str(yaml_file),
          context={"data": {"a": 1, "b": "two"}},
      )
      assert len(resources) == 1
      cm = resources[0]
      assert cm["kind"] == "ConfigMap"
      embedded = cm["data"]["as_yaml"]
      parsed = yaml.safe_load(embedded)
      assert isinstance(parsed, dict)
      assert parsed.get("a") == 1
  
  
  def test_render_template_does_not_autoescape_strings(tmp_path):
      """Ensure tojson output isn't HTML escaped which would break YAML parsing."""
      yaml_file = tmp_path / "labels.yaml"
      yaml_file.write_text(
          textwrap.dedent(
              """\
              apiVersion: v1
              kind: ConfigMap
              metadata:
                name: cm
                labels:
                  foo: {{ value | tojson }}
              data: {}
              """
          )
      )
  
      eng = KubernetesTemplateEngine(strict_undefined=True)
      resources = eng.render_template(
          str(yaml_file),
          context={"value": "abc-123"},
      )
  
      assert resources[0]["metadata"]["labels"]["foo"] == "abc-123"
  