--- - name: Validate Owncast templates without a cluster hosts: localhost connection: local gather_facts: false tasks: - name: Load role defaults and validate them without deploying ansible.builtin.include_role: name: ansible-role-owncast tasks_from: validate.yml public: true - name: Render generic default resources ansible.builtin.set_fact: deployment: "{{ lookup('template', '../templates/deployment.yml.j2') | from_yaml }}" service: "{{ lookup('template', '../templates/service.yml.j2') | from_yaml }}" pvc: "{{ lookup('template', '../templates/pvc.yml.j2') | from_yaml }}" - name: Check private defaults and single-writer safeguards ansible.builtin.assert: that: - deployment.apiVersion == 'apps/v1' - deployment.spec.strategy.type == 'Recreate' - deployment.spec.replicas == 1 - not deployment.spec.template.spec.automountServiceAccountToken - not deployment.spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation - service.spec.type == 'ClusterIP' - "'externalTrafficPolicy' not in service.spec" - "'storageClassName' not in pvc.spec" - pvc.spec.resources.requests.storage == '10Gi' - not owncast_ingress_enabled - not owncast_onion_enabled - name: Load the actual eom playbook variables ansible.builtin.set_fact: "{{ item.key }}": "{{ item.value }}" loop: "{{ (lookup('file', '../playbooks/deploy-eom.yml') | from_yaml)[0].vars | dict2items }}" - name: Validate eom settings ansible.builtin.include_role: name: ansible-role-owncast tasks_from: validate.yml - name: Render eom resources ansible.builtin.set_fact: deployment: "{{ lookup('template', '../templates/deployment.yml.j2') | from_yaml }}" service: "{{ lookup('template', '../templates/service.yml.j2') | from_yaml }}" pvc: "{{ lookup('template', '../templates/pvc.yml.j2') | from_yaml }}" ingress: "{{ lookup('template', '../templates/ingress.yml.j2') | from_yaml }}" onion: "{{ lookup('template', '../templates/onion.yml.j2') | from_yaml }}" - name: Check preservation of existing resource identities and settings ansible.builtin.assert: that: - deployment.metadata.name == 'owncast' - deployment.metadata.namespace == 'owncast' - deployment.spec.selector.matchLabels == {'app':'owncast'} - deployment.spec.template.spec.volumes[0].persistentVolumeClaim.claimName == 'owncast' - deployment.spec.template.spec.containers[0].image == 'owncast/owncast:0.3.0' - deployment.spec.template.spec.containers[0].resources.requests.cpu == '1.5' - deployment.spec.template.spec.containers[0].volumeMounts[0].mountPath == '/app/data' - service.spec.type == 'LoadBalancer' - service.spec.externalTrafficPolicy == 'Local' - service.spec.ports | map(attribute='port') | list == [1935, 8080] - pvc.spec.resources.requests.storage == '128Gi' - ingress.spec.ingressClassName == 'nginx' - ingress.spec.rules[0].host == 'owncast.eom.dev' - ingress.spec.tls[0].secretName == 'owncast' - ingress.metadata.annotations['cert-manager.io/cluster-issuer'] == 'ca-issuer' - onion.metadata.name == 'http' - onion.metadata.namespace == 'owncast' - onion.spec.rules[0].backend.service.name == 'owncast' - onion.spec.rules[0].backend.service.port.number == 8080 - name: Set fake friend settings for validation ansible.builtin.set_fact: friend_owncast_hostname: stream.friend.example.org friend_owncast_cluster_issuer: friend-issuer - name: Load the actual friend playbook variables ansible.builtin.set_fact: "{{ item.key }}": "{{ item.value }}" loop: "{{ (lookup('template', '../playbooks/deploy-friend.yml') | from_yaml)[0].vars | dict2items }}" - name: Validate friend settings ansible.builtin.include_role: name: ansible-role-owncast tasks_from: validate.yml - name: Render friend resources ansible.builtin.set_fact: deployment: "{{ lookup('template', '../templates/deployment.yml.j2') | from_yaml }}" pvc: "{{ lookup('template', '../templates/pvc.yml.j2') | from_yaml }}" ingress: "{{ lookup('template', '../templates/ingress.yml.j2') | from_yaml }}" - name: Check friend isolation ansible.builtin.assert: that: - deployment.metadata.namespace == 'owncast-friend' - deployment.spec.selector.matchLabels == {'app':'owncast-friend'} - deployment.spec.template.spec.volumes[0].persistentVolumeClaim.claimName == 'owncast-friend' - pvc.metadata.name == 'owncast-friend' - ingress.spec.rules[0].host == friend_owncast_hostname - ingress.spec.tls[0].secretName == 'owncast-friend' - ingress.metadata.annotations['cert-manager.io/cluster-issuer'] == friend_owncast_cluster_issuer - not owncast_onion_enabled - name: Exercise existing storage and optional non-TLS ingress ansible.builtin.set_fact: owncast_existing_claim: external-data owncast_storage_class: encrypted-storage owncast_service_type: NodePort owncast_tls_enabled: false owncast_cluster_issuer: "" owncast_ingress_class: "" owncast_ingress_annotations: example.org/test: "true" - name: Render optional configuration ansible.builtin.set_fact: deployment: "{{ lookup('template', '../templates/deployment.yml.j2') | from_yaml }}" pvc: "{{ lookup('template', '../templates/pvc.yml.j2') | from_yaml }}" service: "{{ lookup('template', '../templates/service.yml.j2') | from_yaml }}" ingress: "{{ lookup('template', '../templates/ingress.yml.j2') | from_yaml }}" - name: Check optional configuration ansible.builtin.assert: that: - deployment.spec.template.spec.volumes[0].persistentVolumeClaim.claimName == 'external-data' - pvc.spec.storageClassName == 'encrypted-storage' - service.spec.type == 'NodePort' - service.spec.externalTrafficPolicy == 'Local' - "'tls' not in ingress.spec" - "'ingressClassName' not in ingress.spec" - ingress.metadata.annotations == {'example.org/test':'true'} - name: Set restricted load balancer settings ansible.builtin.set_fact: owncast_service_type: LoadBalancer owncast_load_balancer_source_ranges: [192.0.2.0/24] - name: Check load balancer restrictions ansible.builtin.assert: that: - (lookup('template', '../templates/service.yml.j2') | from_yaml).spec.loadBalancerSourceRanges == ['192.0.2.0/24'] - name: Set invalid DNS hostname ansible.builtin.set_fact: owncast_hostname: https://invalid.example.org/ - name: Check invalid-input rejection block: - name: Run validation with an invalid hostname ansible.builtin.include_role: name: ansible-role-owncast tasks_from: validate.yml - name: Fail if invalid configuration was accepted ansible.builtin.fail: msg: Invalid hostname was accepted rescue: - name: Confirm the expected validation failure ansible.builtin.assert: that: - ansible_failed_task.name == 'Validate Owncast ingress settings'