sdn_tests.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import pytest
  2. from openshift_checks.sdn import SDNCheck
  3. from openshift_checks import OpenShiftCheckException
  4. def fake_execute_module(*args):
  5. raise AssertionError('this function should not be called')
  6. def test_check_nodes_missing_node_name():
  7. task_vars = dict(
  8. group_names=['oo_nodes_to_config'],
  9. )
  10. check = SDNCheck(fake_execute_module, task_vars)
  11. check.run()
  12. assert 1 == len(check.failures)
  13. assert 'Could not determine node name' in str(check.failures[0])
  14. def test_check_master():
  15. nodes = [
  16. {
  17. 'apiVersion': 'v1',
  18. 'kind': 'Node',
  19. 'metadata': {
  20. 'annotations': {'kubernetes.io/hostname': 'node1'},
  21. 'name': 'ip-172-31-50-1.ec2.internal'
  22. },
  23. 'status': {
  24. 'addresses': [
  25. {'address': '172.31.50.1', 'type': 'InternalIP'},
  26. {'address': '52.0.0.1', 'type': 'ExternalIP'},
  27. {
  28. 'address': 'ip-172-31-50-1.ec2.internal',
  29. 'type': 'Hostname'
  30. }
  31. ]
  32. }
  33. },
  34. {
  35. 'apiVersion': 'v1',
  36. 'kind': 'Node',
  37. 'metadata': {'name': 'ip-172-31-50-2.ec2.internal'},
  38. 'status': {
  39. 'addresses': [
  40. {'address': '172.31.50.2', 'type': 'InternalIP'},
  41. {'address': '52.0.0.2', 'type': 'ExternalIP'},
  42. {
  43. 'address': 'ip-172-31-50-2.ec2.internal',
  44. 'type': 'Hostname'
  45. }
  46. ]
  47. }
  48. }
  49. ]
  50. task_vars = dict(
  51. group_names=['oo_masters_to_config'],
  52. resources=dict(results=[
  53. dict(item='nodes', results=dict(results=[dict(items=nodes)])),
  54. dict(item='pods', results=dict(results=[dict(items={})])),
  55. dict(item='services', results=dict(results=[dict(items={})]))
  56. ])
  57. )
  58. node_addresses = {
  59. node['metadata']['name']: {
  60. address['type']: address['address']
  61. for address
  62. in node['status']['addresses']
  63. }
  64. for node in nodes
  65. }
  66. expected_hostnames = [addresses['Hostname']
  67. for addresses in node_addresses.values()]
  68. uri_hostnames = []
  69. resolve_address_hostnames = []
  70. def execute_module(module_name, args, *_):
  71. if module_name == 'uri':
  72. for hostname in expected_hostnames:
  73. if hostname in args['url']:
  74. uri_hostnames.append(hostname)
  75. return {}
  76. raise ValueError('unexpected url: %s' % args['url'])
  77. raise ValueError('not expecting module %s' % module_name)
  78. def resolve_address(address):
  79. for hostname in expected_hostnames:
  80. if address == hostname:
  81. resolve_address_hostnames.append(hostname)
  82. return node_addresses[hostname]['InternalIP']
  83. raise ValueError('unexpected address: %s' % hostname)
  84. check = SDNCheck(execute_module, task_vars)
  85. check.resolve_address = resolve_address
  86. check.run()
  87. assert 0 == len(check.failures)
  88. assert set(expected_hostnames) == set(uri_hostnames), 'should try to connect to the kubelet'
  89. assert set(expected_hostnames) == set(resolve_address_hostnames), 'should try to resolve the node\'s address'
  90. def test_check_nodes():
  91. nodes = [
  92. {
  93. 'apiVersion': 'v1',
  94. 'kind': 'Node',
  95. 'metadata': {
  96. 'annotations': {'kubernetes.io/hostname': 'node1'},
  97. 'name': 'ip-172-31-50-1.ec2.internal'
  98. },
  99. 'status': {
  100. 'addresses': [
  101. {'address': '172.31.50.1', 'type': 'InternalIP'},
  102. {'address': '52.0.0.1', 'type': 'ExternalIP'},
  103. {
  104. 'address': 'ip-172-31-50-1.ec2.internal',
  105. 'type': 'Hostname'
  106. }
  107. ]
  108. }
  109. },
  110. {
  111. 'apiVersion': 'v1',
  112. 'kind': 'Node',
  113. 'metadata': {'name': 'ip-172-31-50-2.ec2.internal'},
  114. 'status': {
  115. 'addresses': [
  116. {'address': '172.31.50.2', 'type': 'InternalIP'},
  117. {'address': '52.0.0.2', 'type': 'ExternalIP'},
  118. {
  119. 'address': 'ip-172-31-50-2.ec2.internal',
  120. 'type': 'Hostname'
  121. }
  122. ]
  123. }
  124. }
  125. ]
  126. hostsubnets = [
  127. {
  128. 'metadata': {
  129. 'name': 'ip-172-31-50-1.ec2.internal'
  130. },
  131. 'subnet': '10.128.0.1/23'
  132. },
  133. {
  134. 'metadata': {
  135. 'name': 'ip-172-31-50-2.ec2.internal'
  136. },
  137. 'subnet': '10.129.0.1/23'
  138. }
  139. ]
  140. task_vars = dict(
  141. group_names=['oo_nodes_to_config'],
  142. resources=dict(results=[
  143. dict(item='nodes', results=dict(results=[dict(items=nodes)])),
  144. dict(item='hostsubnets', results=dict(results=[dict(items=hostsubnets)]))
  145. ]),
  146. openshift=dict(node=dict(nodename='foo'))
  147. )
  148. def execute_module(module_name, args, *_):
  149. if module_name == 'command':
  150. return dict(stdout='bogus_container_id')
  151. raise ValueError('not expecting module %s' % module_name)
  152. SDNCheck(execute_module, task_vars).run()
  153. def test_resolve_address():
  154. def execute_module(module_name, args, *_):
  155. if module_name != 'command':
  156. raise ValueError('not expecting module %s' % module_name)
  157. command_args = args['_raw_params'].split()
  158. if command_args[0] != '/bin/getent':
  159. raise ValueError('not expecting command: %s' % args.raw_params)
  160. # The expected command_args is ['/bin/getent', 'ahostsv4', 'foo'].
  161. if command_args[2] == 'foo':
  162. return {
  163. 'rc': 0,
  164. 'stdout': '''1.2.3.4 STREAM bar
  165. 1.2.3.4 DGRAM
  166. 1.2.3.4 RAW
  167. '''
  168. }
  169. return {'rc': 2}
  170. check = SDNCheck(execute_module, None)
  171. assert check.resolve_address('foo') == '1.2.3.4'
  172. with pytest.raises(OpenShiftCheckException):
  173. check.resolve_address('baz')
  174. def test_no_nodes():
  175. task_vars = dict(
  176. group_names=['oo_masters_to_config'],
  177. resources=dict(results=[
  178. dict(item='nodes', results=dict(results=[dict(items={})])),
  179. dict(item='pods', results=dict(results=[dict(items={})])),
  180. dict(item='services', results=dict(results=[dict(items={})]))
  181. ])
  182. )
  183. check = SDNCheck(fake_execute_module, task_vars)
  184. check.run()
  185. assert 1 == len(check.failures)
  186. assert 'No nodes' in str(check.failures[0])
  187. @pytest.mark.parametrize('group_names,expected', [
  188. (['oo_masters_to_config'], True),
  189. (['oo_nodes_to_config'], True),
  190. (['oo_masters_to_config', 'oo_nodes_to_config'], True),
  191. (['oo_masters_to_config', 'oo_etcd_to_config'], True),
  192. ([], False),
  193. (['oo_etcd_to_config'], False),
  194. (['lb'], False),
  195. (['nfs'], False),
  196. ])
  197. def test_sdn_skip_when_not_master_nor_node(group_names, expected):
  198. task_vars = dict(
  199. group_names=group_names,
  200. )
  201. assert SDNCheck(None, task_vars).is_active() == expected