Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 1 | # Copyright 2017 Mirantis, Inc. |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 4 | # not use this file except in compliance with the License. You may obtain |
| 5 | # a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations |
| 13 | # under the License. |
| 14 | |
| 15 | import pytest |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 16 | import netaddr |
| 17 | import os |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 18 | import json |
Vladimir Jigulin | 5775bbb | 2018-10-03 10:34:54 +0400 | [diff] [blame] | 19 | import requests |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 20 | |
| 21 | from tcp_tests import logger |
| 22 | from tcp_tests import settings |
| 23 | |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 24 | from tcp_tests.managers.k8s import read_yaml_file |
| 25 | |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 26 | LOG = logger.logger |
| 27 | |
| 28 | |
| 29 | class TestMCPK8sActions(object): |
| 30 | """Test class for different k8s actions""" |
| 31 | |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 32 | def __read_testdata_yaml(self, name): |
| 33 | dir = os.path.join(os.path.dirname(__file__), 'testdata/k8s') |
| 34 | return read_yaml_file(dir, name) |
| 35 | |
Tatyana Leontovich | c411ec3 | 2017-10-09 14:48:00 +0300 | [diff] [blame] | 36 | @pytest.mark.grab_versions |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 37 | @pytest.mark.fail_snapshot |
Tatyana Leontovich | 071ce6a | 2017-10-24 18:08:10 +0300 | [diff] [blame] | 38 | @pytest.mark.cz8116 |
Dennis Dmitriev | 0f624a8 | 2018-06-11 12:57:13 +0300 | [diff] [blame] | 39 | @pytest.mark.k8s_calico |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 40 | def test_k8s_externaldns_coredns(self, show_step, config, k8s_deployed): |
| 41 | """Test externaldns integration with coredns |
| 42 | |
| 43 | Scenario: |
| 44 | 1. Install k8s with externaldns addon enabled(including etcd, coredns) |
| 45 | 2. Start simple service |
| 46 | 3. Expose deployment |
| 47 | 4. Annotate service with domain name |
| 48 | 5. Try to get service using nslookup |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 49 | 6. Delete service and deployment |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 50 | """ |
| 51 | |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 52 | show_step(1) |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 53 | if not (config.k8s_deploy.kubernetes_externaldns_enabled and |
| 54 | config.k8s_deploy.kubernetes_coredns_enabled): |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 55 | pytest.skip("Test requires externaldns and coredns addons enabled") |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 56 | |
| 57 | show_step(2) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 58 | deployment = k8s_deployed.run_sample_deployment('test-dep') |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 59 | |
| 60 | show_step(3) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 61 | svc = deployment.expose() |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 62 | |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 63 | show_step(4) |
Vladimir Jigulin | 7eb41b0 | 2018-10-24 17:03:51 +0400 | [diff] [blame] | 64 | hostname = "test.{0}.".format(settings.DOMAIN_NAME) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 65 | svc.patch({ |
| 66 | "metadata": { |
| 67 | "annotations": { |
| 68 | "external-dns.alpha.kubernetes.io/hostname": hostname |
| 69 | } |
| 70 | } |
| 71 | }) |
Victor Ryzhenkin | 14354ac | 2017-09-27 17:42:30 +0400 | [diff] [blame] | 72 | |
| 73 | show_step(5) |
Vladimir Jigulin | 9068915 | 2018-09-26 15:38:19 +0400 | [diff] [blame] | 74 | dns_svc = k8s_deployed.api.services.get( |
| 75 | name='coredns', namespace='kube-system') |
| 76 | k8s_deployed.nslookup(hostname, dns_svc.get_ip()) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 77 | |
| 78 | show_step(6) |
| 79 | deployment.delete() |
Victor Ryzhenkin | 87a3142 | 2018-03-16 22:25:27 +0400 | [diff] [blame] | 80 | |
| 81 | @pytest.mark.grab_versions |
| 82 | @pytest.mark.cncf_publisher(name=['e2e.log', 'junit_01.xml', 'version.txt', |
| 83 | 'cncf_results.tar.gz']) |
| 84 | @pytest.mark.fail_snapshot |
| 85 | def test_k8s_cncf_certification(self, show_step, config, k8s_deployed, |
Vladimir Jigulin | 0c8dd5a | 2018-08-28 05:08:35 +0400 | [diff] [blame] | 86 | k8s_cncf_log_helper): |
Victor Ryzhenkin | 87a3142 | 2018-03-16 22:25:27 +0400 | [diff] [blame] | 87 | """Run cncf e2e suite and provide files needed for pull request |
| 88 | to the CNCF repo |
| 89 | |
| 90 | Scenario: |
| 91 | 1. Run cncf from https://github.com/cncf/k8s-conformance |
| 92 | """ |
| 93 | |
| 94 | show_step(1) |
| 95 | k8s_deployed.start_k8s_cncf_verification() |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 96 | |
| 97 | @pytest.mark.grap_versions |
| 98 | @pytest.mark.fail_snapshot |
| 99 | def test_k8s_chain_update(self, show_step, underlay, config, k8s_deployed, |
| 100 | k8s_chain_update_log_helper): |
| 101 | """Test for chain-upgrading k8s hypercube pool and checking it |
| 102 | |
| 103 | Scenario: |
| 104 | 1. Prepare salt on hosts |
| 105 | 2. Setup controller nodes |
| 106 | 3. Setup compute nodes |
| 107 | 4. Setup Kubernetes cluster |
| 108 | 5. Run and expose sample test service |
| 109 | 6. Run conformance to check consistency |
| 110 | 7. For every version in update chain: |
| 111 | Update cluster to new version, check test sample service |
| 112 | availability, run conformance |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 113 | 8. Delete service and deployment |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 114 | """ |
| 115 | |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 116 | show_step(5) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 117 | sample = k8s_deployed.run_sample_deployment('test-dep-chain-upgrade') |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 118 | sample.expose() |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 119 | sample.wait_ready() |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 120 | |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 121 | assert sample.is_service_available() |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 122 | |
| 123 | show_step(6) |
| 124 | k8s_deployed.run_conformance(log_out="k8s_conformance.log") |
| 125 | |
| 126 | show_step(7) |
| 127 | chain_versions = config.k8s.k8s_update_chain.split(" ") |
| 128 | for version in chain_versions: |
| 129 | LOG.info("Chain update to '{}' version".format(version)) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 130 | k8s_deployed.update_k8s_version(version) |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 131 | |
| 132 | LOG.info("Checking test service availability") |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 133 | assert sample.is_service_available() |
Vladimir Jigulin | 62bcf46 | 2018-05-28 18:17:01 +0400 | [diff] [blame] | 134 | |
| 135 | LOG.info("Running conformance on {} version".format(version)) |
| 136 | log_name = "k8s_conformance_{}.log".format(version) |
| 137 | k8s_deployed.run_conformance(log_out=log_name, raise_on_err=False) |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 138 | |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 139 | assert sample.is_service_available() |
| 140 | |
| 141 | show_step(8) |
| 142 | sample.delete() |
| 143 | |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 144 | @pytest.mark.grap_versions |
| 145 | @pytest.mark.fail_snapshot |
Dennis Dmitriev | 66650fc | 2018-11-02 11:04:37 +0200 | [diff] [blame^] | 146 | @pytest.mark.k8s_metallb |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 147 | def test_k8s_metallb(self, show_step, config, k8s_deployed): |
| 148 | """Enable metallb in cluster and do basic tests |
| 149 | |
| 150 | Scenario: |
| 151 | 1. Setup Kubernetes cluster with enabled metallb |
| 152 | 2. Check that metallb pods created in metallb-system namespace |
| 153 | 3. Run 5 sample deployments |
| 154 | 4. Expose deployments with type=LoadBalancer |
| 155 | 5. Check services availability from outside of cluster |
| 156 | 6. Run conformance |
| 157 | 7. Check services availability from outside of cluster |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 158 | 8. Delete deployments |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 159 | """ |
| 160 | show_step(1) |
Dennis Dmitriev | 66650fc | 2018-11-02 11:04:37 +0200 | [diff] [blame^] | 161 | if not k8s_deployed.is_metallb_enabled: |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 162 | pytest.skip("Test requires metallb addon enabled") |
| 163 | |
| 164 | show_step(2) |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 165 | ns = "metallb-system" |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 166 | assert \ |
| 167 | len(k8s_deployed.api.pods.list(ns, name_prefix="controller")) > 0 |
| 168 | assert \ |
| 169 | len(k8s_deployed.api.pods.list(ns, name_prefix="speaker")) > 0 |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 170 | |
| 171 | show_step(3) |
| 172 | samples = [] |
| 173 | for i in range(5): |
| 174 | name = 'test-dep-metallb-{}'.format(i) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 175 | samples.append(k8s_deployed.run_sample_deployment(name)) |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 176 | |
| 177 | show_step(4) |
| 178 | for sample in samples: |
| 179 | sample.expose('LoadBalancer') |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 180 | sample.wait_ready() |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 181 | |
| 182 | show_step(5) |
| 183 | for sample in samples: |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 184 | assert sample.is_service_available(external=False) |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 185 | assert sample.is_service_available(external=True) |
| 186 | |
| 187 | show_step(6) |
| 188 | k8s_deployed.run_conformance() |
| 189 | |
| 190 | show_step(7) |
| 191 | for sample in samples: |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 192 | assert sample.is_service_available(external=False) |
Vladimir Jigulin | a6b018b | 2018-07-18 15:19:01 +0400 | [diff] [blame] | 193 | assert sample.is_service_available(external=True) |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 194 | |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 195 | show_step(8) |
| 196 | for sample in samples: |
| 197 | sample.delete() |
| 198 | |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 199 | @pytest.mark.grap_versions |
| 200 | @pytest.mark.fail_snapshot |
Dennis Dmitriev | ee5ef23 | 2018-08-31 13:53:18 +0300 | [diff] [blame] | 201 | @pytest.mark.k8s_genie |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 202 | def test_k8s_genie_flannel(self, show_step, config, |
| 203 | salt_deployed, k8s_deployed): |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 204 | """Test genie-cni+flannel cni setup |
| 205 | |
| 206 | Scenario: |
| 207 | 1. Setup Kubernetes cluster with genie cni and flannel |
| 208 | 2. Check that flannel pods created in kube-system namespace |
| 209 | 3. Create sample deployment with flannel cni annotation |
| 210 | 4. Check that the deployment have 1 ip addresses from cni provider |
| 211 | 5. Create sample deployment with calico cni annotation |
| 212 | 6. Check that the deployment have 1 ip addresses from cni provider |
| 213 | 7. Create sample deployment with multi-cni annotation |
| 214 | 8. Check that the deployment have 2 ip addresses from different |
| 215 | cni providers |
| 216 | 9. Create sample deployment without cni annotation |
| 217 | 10. Check that the deployment have 1 ip address |
| 218 | 11. Check pods availability |
| 219 | 12. Run conformance |
| 220 | 13. Check pods availability |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 221 | 14. Delete pods |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 222 | """ |
| 223 | show_step(1) |
| 224 | |
| 225 | # Find out calico and flannel networks |
Victor Ryzhenkin | 0c37382 | 2018-10-30 17:55:50 +0400 | [diff] [blame] | 226 | tgt_k8s_control = "I@kubernetes:master" |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 227 | |
| 228 | flannel_pillar = salt_deployed.get_pillar( |
| 229 | tgt=tgt_k8s_control, |
| 230 | pillar="kubernetes:master:network:flannel:private_ip_range")[0] |
| 231 | flannel_network = netaddr.IPNetwork(flannel_pillar.values()[0]) |
| 232 | LOG.info("Flannel network: {}".format(flannel_network)) |
| 233 | |
| 234 | calico_network_pillar = salt_deployed.get_pillar( |
| 235 | tgt=tgt_k8s_control, pillar="_param:calico_private_network")[0] |
| 236 | calico_netmask_pillar = salt_deployed.get_pillar( |
| 237 | tgt=tgt_k8s_control, pillar="_param:calico_private_netmask")[0] |
| 238 | calico_network = netaddr.IPNetwork( |
| 239 | "{0}/{1}".format(calico_network_pillar.values()[0], |
| 240 | calico_netmask_pillar.values()[0])) |
| 241 | LOG.info("Calico network: {}".format(calico_network)) |
| 242 | |
| 243 | show_step(2) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 244 | assert k8s_deployed.api.pods.list( |
| 245 | namespace="kube-system", name_prefix="kube-flannel-") > 0 |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 246 | |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 247 | show_step(3) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 248 | flannel_pod = k8s_deployed.api.pods.create( |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 249 | body=self.__read_testdata_yaml('pod-sample-flannel.yaml')) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 250 | flannel_pod.wait_running() |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 251 | |
| 252 | show_step(4) |
| 253 | flannel_ips = k8s_deployed.get_pod_ips_from_container(flannel_pod.name) |
| 254 | assert len(flannel_ips) == 1 |
| 255 | assert netaddr.IPAddress(flannel_ips[0]) in flannel_network |
| 256 | |
| 257 | show_step(5) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 258 | calico_pod = k8s_deployed.api.pods.create( |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 259 | body=self.__read_testdata_yaml('pod-sample-calico.yaml')) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 260 | calico_pod.wait_running() |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 261 | |
| 262 | show_step(6) |
| 263 | calico_ips = k8s_deployed.get_pod_ips_from_container(calico_pod.name) |
| 264 | assert len(calico_ips) == 1 |
| 265 | assert netaddr.IPAddress(calico_ips[0]) in calico_network |
| 266 | |
| 267 | show_step(7) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 268 | multicni_pod = k8s_deployed.api.pods.create( |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 269 | body=self.__read_testdata_yaml('pod-sample-multicni.yaml')) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 270 | multicni_pod.wait_running() |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 271 | |
| 272 | show_step(8) |
| 273 | multicni_ips = \ |
| 274 | k8s_deployed.get_pod_ips_from_container(multicni_pod.name) |
| 275 | assert len(multicni_ips) == 2 |
| 276 | for net in [calico_network, flannel_network]: |
| 277 | assert netaddr.IPAddress(multicni_ips[0]) in net or \ |
| 278 | netaddr.IPAddress(multicni_ips[1]) in net |
| 279 | |
| 280 | show_step(9) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 281 | nocni_pod = k8s_deployed.api.pods.create( |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 282 | body=self.__read_testdata_yaml('pod-sample.yaml')) |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 283 | nocni_pod.wait_running() |
Vladimir Jigulin | 34dfa94 | 2018-07-23 21:05:48 +0400 | [diff] [blame] | 284 | |
| 285 | show_step(10) |
| 286 | nocni_ips = k8s_deployed.get_pod_ips_from_container(nocni_pod.name) |
| 287 | assert len(nocni_ips) == 1 |
| 288 | assert (netaddr.IPAddress(nocni_ips[0]) in calico_network or |
| 289 | netaddr.IPAddress(nocni_ips[0]) in flannel_network) |
| 290 | |
| 291 | show_step(11) |
| 292 | |
| 293 | def check_pod_availability(ip): |
| 294 | assert "Hello Kubernetes!" in k8s_deployed.curl( |
| 295 | "http://{}:8080".format(ip)) |
| 296 | |
| 297 | def check_pods_availability(): |
| 298 | check_pod_availability(flannel_ips[0]) |
| 299 | check_pod_availability(calico_ips[0]) |
| 300 | check_pod_availability(multicni_ips[0]) |
| 301 | check_pod_availability(multicni_ips[1]) |
| 302 | check_pod_availability(nocni_ips[0]) |
| 303 | |
| 304 | check_pods_availability() |
| 305 | |
| 306 | show_step(12) |
| 307 | k8s_deployed.run_conformance() |
| 308 | |
| 309 | show_step(13) |
| 310 | check_pods_availability() |
Vladimir Jigulin | 4ad52a8 | 2018-08-12 05:51:30 +0400 | [diff] [blame] | 311 | |
| 312 | show_step(14) |
| 313 | flannel_pod.delete() |
| 314 | calico_pod.delete() |
| 315 | multicni_pod.delete() |
| 316 | nocni_pod.delete() |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 317 | |
| 318 | @pytest.mark.grap_versions |
| 319 | @pytest.mark.fail_snapshot |
Dennis Dmitriev | 66650fc | 2018-11-02 11:04:37 +0200 | [diff] [blame^] | 320 | @pytest.mark.k8s_dashboard |
Vladimir Jigulin | 57ecae9 | 2018-09-10 22:51:15 +0400 | [diff] [blame] | 321 | def test_k8s_dashboard(self, show_step, config, |
| 322 | salt_deployed, k8s_deployed): |
| 323 | """Test dashboard setup |
| 324 | |
| 325 | Scenario: |
| 326 | 1. Setup Kubernetes cluster |
| 327 | 2. Try to curl login status api |
| 328 | 3. Create a test-admin-user account |
| 329 | 4. Try to login in dashboard using test-admin-user account |
| 330 | 5. Get and check list of namespaces using dashboard api |
| 331 | """ |
| 332 | show_step(1) |
| 333 | |
| 334 | show_step(2) |
| 335 | system_ns = 'kube-system' |
| 336 | dashboard_service = \ |
| 337 | k8s_deployed.api.services.get('kubernetes-dashboard', system_ns) |
| 338 | dashboard_url = 'https://{}'.format(dashboard_service.get_ip()) |
| 339 | |
| 340 | def dashboard_curl(url, data=None, headers=None): |
| 341 | """ Using curl command on controller node. Alternatives: |
| 342 | - connect_{get,post}_namespaced_service_proxy_with_path - |
| 343 | k8s lib does not provide way to pass headers or POST data |
| 344 | - raw rest k8s api - need to auth somehow |
| 345 | - new load-balancer svc for dashboard + requests python lib - |
| 346 | requires working metallb or other load-balancer |
| 347 | """ |
| 348 | args = ['--insecure'] |
| 349 | for name in headers or {}: |
| 350 | args.append('--header') |
| 351 | args.append("{0}: {1}".format(name, headers[name])) |
| 352 | if data is not None: |
| 353 | args.append('--data') |
| 354 | args.append(data) |
| 355 | return ''.join(k8s_deployed.curl(dashboard_url + url, *args)) |
| 356 | |
| 357 | assert 'tokenPresent' in \ |
| 358 | json.loads(dashboard_curl('/api/v1/login/status')) |
| 359 | |
| 360 | show_step(3) |
| 361 | account = k8s_deployed.api.serviceaccounts.create( |
| 362 | namespace=system_ns, |
| 363 | body=self.__read_testdata_yaml('test-admin-user-account.yaml')) |
| 364 | account.wait_secret_generation() |
| 365 | |
| 366 | k8s_deployed.api.clusterrolebindings.create( |
| 367 | body=self.__read_testdata_yaml( |
| 368 | 'test-admin-user-cluster-role-bind.yaml')) |
| 369 | |
| 370 | account_secret = account.read().secrets[0] |
| 371 | account_token = k8s_deployed.api.secrets.get( |
| 372 | namespace=system_ns, name=account_secret.name).read().data['token'] |
| 373 | |
| 374 | show_step(4) |
| 375 | csrf_token = \ |
| 376 | json.loads(dashboard_curl('/api/v1/csrftoken/login'))['token'] |
| 377 | login_headers = {'X-CSRF-TOKEN': csrf_token, |
| 378 | 'Content-Type': 'application/json'} |
| 379 | jwe_token = json.loads(dashboard_curl( |
| 380 | '/api/v1/login', headers=login_headers, |
| 381 | data=json.dumps({'token': account_token.decode('base64')}) |
| 382 | ))['jweToken'] |
| 383 | headers = {'jweToken': jwe_token} |
| 384 | |
| 385 | show_step(5) |
| 386 | dashboard_namespaces = json.loads( |
| 387 | dashboard_curl('/api/v1/namespace', headers=headers))['namespaces'] |
| 388 | |
| 389 | namespaces_names_list = \ |
| 390 | [ns.name for ns in k8s_deployed.api.namespaces.list()] |
| 391 | for namespace in dashboard_namespaces: |
| 392 | assert namespace['objectMeta']['name'] in namespaces_names_list |
Vladimir Jigulin | 5775bbb | 2018-10-03 10:34:54 +0400 | [diff] [blame] | 393 | |
| 394 | @pytest.mark.grap_versions |
| 395 | @pytest.mark.fail_snapshot |
Dennis Dmitriev | 66650fc | 2018-11-02 11:04:37 +0200 | [diff] [blame^] | 396 | @pytest.mark.k8s_ingress_nginx |
Vladimir Jigulin | 5775bbb | 2018-10-03 10:34:54 +0400 | [diff] [blame] | 397 | def test_k8s_ingress_nginx(self, show_step, config, |
| 398 | salt_deployed, k8s_deployed): |
| 399 | """Test ingress-nginx configured and working with metallb |
| 400 | |
| 401 | Scenario: |
| 402 | 1. Setup Kubernetes cluster with metallb |
| 403 | 2. Create 2 example deployments and expose them |
| 404 | 3. Create ingress controller with 2 backends to each deployment |
| 405 | service respectively |
| 406 | 4. Wait ingress for deploy |
| 407 | 5. Try to reach default endpoint |
| 408 | 6. Try to reach test1 and test2 deployment services endpoints |
| 409 | """ |
| 410 | show_step(1) |
Dennis Dmitriev | 66650fc | 2018-11-02 11:04:37 +0200 | [diff] [blame^] | 411 | if not k8s_deployed.is_metallb_enabled: |
Vladimir Jigulin | 5775bbb | 2018-10-03 10:34:54 +0400 | [diff] [blame] | 412 | pytest.skip("Test requires metallb addon enabled") |
Dennis Dmitriev | 66650fc | 2018-11-02 11:04:37 +0200 | [diff] [blame^] | 413 | if not k8s_deployed.is_ingress_nginx_enabled: |
Vladimir Jigulin | 5775bbb | 2018-10-03 10:34:54 +0400 | [diff] [blame] | 414 | pytest.skip("Test requires ingress-nginx addon enabled") |
| 415 | |
| 416 | show_step(2) |
| 417 | image = 'nginxdemos/hello:plain-text' |
| 418 | port = 80 |
| 419 | dep1 = k8s_deployed.run_sample_deployment( |
| 420 | 'dep-ingress-1', image=image, port=port) |
| 421 | dep2 = k8s_deployed.run_sample_deployment( |
| 422 | 'dep-ingress-2', image=image, port=port) |
| 423 | svc1 = dep1.wait_ready().expose() |
| 424 | svc2 = dep2.wait_ready().expose() |
| 425 | |
| 426 | show_step(3) |
| 427 | body = { |
| 428 | 'apiVersion': 'extensions/v1beta1', |
| 429 | 'kind': 'Ingress', |
| 430 | 'metadata': {'name': 'ingress-test'}, |
| 431 | 'spec': { |
| 432 | 'rules': [{'http': { |
| 433 | 'paths': [{ |
| 434 | 'backend': { |
| 435 | 'serviceName': svc1.name, |
| 436 | 'servicePort': port}, |
| 437 | 'path': '/test1'}, { |
| 438 | 'backend': { |
| 439 | 'serviceName': svc2.name, |
| 440 | 'servicePort': port}, |
| 441 | 'path': '/test2' |
| 442 | }] |
| 443 | }}] |
| 444 | } |
| 445 | } |
| 446 | ingress = k8s_deployed.api.ingresses.create(body=body) |
| 447 | |
| 448 | show_step(4) |
| 449 | ingress.wait_ready() |
| 450 | |
| 451 | show_step(5) |
| 452 | ingress_address = "https://{}".format( |
| 453 | ingress.read().status.load_balancer.ingress[0].ip) |
| 454 | |
| 455 | assert requests.get(ingress_address, verify=False).status_code == 404 |
| 456 | |
| 457 | show_step(6) |
| 458 | req1 = requests.get(ingress_address + "/test1", verify=False) |
| 459 | assert req1.status_code == 200 |
| 460 | assert 'dep-ingress-1' in req1.text |
| 461 | |
| 462 | req2 = requests.get(ingress_address + "/test2", verify=False) |
| 463 | assert req2.status_code == 200 |
| 464 | assert 'dep-ingress-2' in req2.text |