promenade/tests/unit/api/test_validatedesign.py
Wahlstedt, Walter (ww229g) 8ce937a9f7 updates for focal
add focal dockerfile
update zuul jobs for focal
update tox for tox4 changes
update all requirements to latest and match deckhand
update cfssl from R1.2 to v1.6.3
fixed local gates for focal
updated examples promenade manifests to run on focal

Change-Id: I2af4043784766d36588c6f738053ad66e7b89a90
2023-02-27 12:11:07 -05:00

268 lines
12 KiB
Python

# 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:master-ubuntu_bionic',
'kubernetes': {
'apiserver':
'k8s.gcr.io/kube-apiserver-amd64:v1.24.4',
'controller-manager':
'k8s.gcr.io/kube-controller-manager-amd64:v1.24.4',
'etcd':
'quay.io/coreos/etcd:v3.5.4',
'scheduler':
'k8s.gcr.io/kube-scheduler-amd64:v1.24.4'
}
},
'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.24.4/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:1.8.3',
'helm': {
'helm': 'lachlanevenson/k8s-helm:v3.9.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': 'k8s.gcr.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