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