# Copyright 2017 AT&T Intellectual Property.  All other 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
#
#    http://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.

from falcon import testing
from promenade import promenade
from promenade.control import health_api
from unittest import mock
import copy
import falcon
import json
import pytest


@pytest.fixture()
def client():
    return testing.TestClient(promenade.start_promenade(disable='keystone'))


@pytest.fixture()
def std_headers():
    return {
        'Content-Type': 'application/json',
        'X-IDENTITY-STATUS': 'Confirmed',
        'X-USER-NAME': 'Test',
        'X-ROLES': 'admin'
    }


@pytest.fixture()
def std_body():
    return json.dumps({
        'rel': 'design',
        'href': 'http://localhost:9999',
        'type': 'application/x-yaml',
    })


def test_post_validatedesign_empty_docs(client, std_body, std_headers):
    with mock.patch('promenade.design_ref.get_documents') as gd:
        gd.return_value = ([], False)
        response = client.simulate_post('/api/v1.0/validatedesign',
                                        headers=std_headers,
                                        body=std_body)
    assert response.status == falcon.HTTP_400
    assert response.json['details']['errorCount'] == 5


VALID_DOCS = [
    {
        'data': {
            'config': {
                'insecure-registries': ['registry:5000'],
                'live-restore': True,
                'max-concurrent-downloads': 10,
                'oom-score-adjust': -999,
                'storage-driver': 'overlay2'
            }
        },
        'metadata': {
            'layeringDefinition': {
                'abstract': False,
                'layer': 'site'
            },
            'name': 'docker',
            'schema': 'metadata/Document/v1',
            'storagePolicy': 'cleartext'
        },
        'schema': 'promenade/Docker/v1'
    },
    {
        'data': {
            'apiserver': {
                'command_prefix': [
                    '/apiserver', '--authorization-mode=Node,RBAC',
                    '--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds',
                    '--service-cluster-ip-range=10.96.0.0/16',
                    '--endpoint-reconciler-type=lease'
                ]
            },
            'armada': {
                'target_manifest': 'cluster-bootstrap'
            },
            'files': [{
                'content':
                '# placeholder for triggering calico etcd bootstrapping',
                'mode': 420,
                'path': '/var/lib/anchor/calico-etcd-bootstrap'
            }],
            'hostname':
            'n0',
            'images': {
                'armada': 'quay.io/airshipit/armada:latest-ubuntu_focal',
                'armada-operator': 'quay.io/airshipit/armada-operator:latest',
                'kubernetes': {
                    'apiserver':
                    'registry.k8s.io/kube-apiserver-amd64:v1.32.1',
                    'controller-manager':
                    'registry.k8s.io/kube-controller-manager-amd64:v1.32.1',
                    'etcd': 'quay.io/coreos/etcd:v3.5.12',
                    'scheduler': 'registry.k8s.io/kube-scheduler-amd64:v1.32.1'
                }
            },
            'ip':
            '192.168.77.10',
            'labels': {
                'dynamic': [
                    'calico-etcd=enabled', 'coredns=enabled',
                    'kubernetes-apiserver=enabled',
                    'kubernetes-controller-manager=enabled',
                    'kubernetes-etcd=enabled', 'kubernetes-scheduler=enabled',
                    'promenade-genesis=enabled', 'ucp-control-plane=enabled'
                ]
            }
        },
        'metadata': {
            'layeringDefinition': {
                'abstract': False,
                'layer': 'site'
            },
            'name': 'genesis',
            'schema': 'metadata/Document/v1'
        },
        'schema': 'promenade/Genesis/v1'
    },
    {
        'data': {
            'files': [{
                'mode':
                365,
                'path':
                '/opt/kubernetes/bin/kubelet',
                'tar_path':
                'kubernetes/node/bin/kubelet',
                'tar_url':
                'https://dl.k8s.io/v1.32.1/kubernetes-node-linux-amd64.tar.gz'
            }, {
                'content':
                '/var/lib/docker/containers/*/*-json.log\n{\n    compress\n    copytruncate\n    create 0644 root root\n    daily\n    dateext\n    dateformat -%Y%m%d-%s\n    maxsize 10M\n    missingok\n    notifempty\n    su root root\n    rotate 1\n}',
                'mode': 292,
                'path': '/etc/logrotate.d/json-logrotate'
            }],
            'images': {
                'haproxy': 'haproxy:2.4',
                'helm': {
                    'helm': 'lachlanevenson/k8s-helm:v3.16.4'
                }
            },
            'packages': {
                'additional': ['curl', 'jq'],
                'keys': [
                    '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n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\nYT90qFF93M3v01BbxP+EIY2/9tiIPbrd\n=0YYh\n-----END PGP PUBLIC KEY BLOCK-----'
                ],
                'repositories': [
                    'deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable'
                ],
                'required': {
                    'docker': 'docker-ce=5:19.03.8~3-0~ubuntu-bionic',
                    'socat': 'socat=1.7.3.1-1'
                }
            },
            'validation': {
                'pod_logs': {
                    'image': 'busybox:1.28.3'
                }
            }
        },
        'metadata': {
            'layeringDefinition': {
                'abstract': False,
                'layer': 'site'
            },
            'name': 'host-system',
            'schema': 'metadata/Document/v1'
        },
        'schema': 'promenade/HostSystem/v1'
    },
    {
        'data': {
            'arguments': ['--v=5'],
            'images': {
                'pause': 'registry.k8s.io/pause-amd64:3.1'
            },
            'config_file_overrides': {
                'evictionMaxPodGracePeriod': -1,
                'nodeStatusUpdateFrequency': '5s',
                'serializeImagePulls': 'false'
            }
        },
        'metadata': {
            'layeringDefinition': {
                'abstract': False,
                'layer': 'site'
            },
            'name': 'kubelet',
            'schema': 'metadata/Document/v1',
            'storagePolicy': 'cleartext'
        },
        'schema': 'promenade/Kubelet/v1'
    },
    {
        'data': {
            'dns': {
                'bootstrap_validation_checks': [
                    'calico-etcd.kube-system.svc.cluster.local', 'google.com',
                    'kubernetes-etcd.kube-system.svc.cluster.local',
                    'kubernetes.default.svc.cluster.local'
                ],
                'cluster_domain':
                'cluster.local',
                'service_ip':
                '10.96.0.10',
                'upstream_servers': ['8.8.8.8', '8.8.4.4']
            },
            'etcd': {
                'container_port': 2379,
                'haproxy_port': 2378
            },
            'hosts_entries': [{
                'ip': '192.168.77.1',
                'names': ['registry']
            }],
            'kubernetes': {
                'apiserver_port': 6443,
                'haproxy_port': 6553,
                'pod_cidr': '10.97.0.0/16',
                'service_cidr': '10.96.0.0/16',
                'service_ip': '10.96.0.1'
            }
        },
        'metadata': {
            'layeringDefinition': {
                'abstract': False,
                'layer': 'site'
            },
            'name': 'kubernetes-network',
            'schema': 'metadata/Document/v1',
            'storagePolicy': 'cleartext'
        },
        'schema': 'promenade/KubernetesNetwork/v1'
    },
]


def test_post_validatedesign_valid_docs(client, std_body, std_headers):
    with mock.patch('promenade.design_ref.get_documents') as gd:
        gd.return_value = (VALID_DOCS, False)
        response = client.simulate_post('/api/v1.0/validatedesign',
                                        headers=std_headers,
                                        body=std_body)
    assert response.status == falcon.HTTP_200
    assert response.json['details']['errorCount'] == 0