@EndpointDoc("List Host Specifications",
parameters={
'sources': (str, 'Host Sources'),
- 'facts': (bool, 'Host Facts')
+ 'facts': (bool, 'Host Facts'),
+ 'include_service_instances': (bool, 'Include Service Instances')
},
responses={200: LIST_HOST_SCHEMA})
@RESTController.MethodMap(version=APIVersion(1, 3))
def list(self, sources=None, facts=False, offset: int = 0,
- limit: int = 5, search: str = '', sort: str = ''):
+ limit: int = 5, search: str = '', sort: str = '',
+ include_service_instances=True):
hosts = get_hosts(sources)
params = ['hostname']
paginator = ListPaginator(int(offset), int(limit), sort, search, hosts,
for host in hosts:
if 'services' not in host:
host['services'] = []
- host['service_instances'] = populate_service_instances(
- host['hostname'], host['services'])
+ if str_to_bool(include_service_instances):
+ host['service_instances'] = populate_service_instances(
+ host['hostname'], host['services'])
if str_to_bool(facts):
if orch.available():
if not orch.get_missing_features(['get_facts']):
expect(spans[0].textContent.trim()).toBe(hostname);
});
- it('should show the exact count of the repeating daemons', () => {
- const hostname = 'ceph.dev';
- const payload = [
- {
- service_instances: [
- {
- type: 'mgr',
- count: 2
- },
- {
- type: 'osd',
- count: 3
- },
- {
- type: 'rgw',
- count: 1
- }
- ],
- hostname: hostname,
- labels: ['foo', 'bar'],
- headers: headers
- }
- ];
-
- OrchestratorHelper.mockStatus(false);
- fixture.detectChanges();
- hostListSpy.and.callFake(() => of(payload));
- fixture.detectChanges();
-
- component.getHosts(new CdTableFetchDataContext(() => undefined));
- fixture.detectChanges();
-
- const spans = fixture.debugElement.nativeElement.querySelectorAll(
- '[cdstabledata] span span.badge.badge-background-primary'
- );
- expect(spans[0].textContent).toContain('mgr: 2');
- expect(spans[1].textContent).toContain('osd: 3');
- expect(spans[2].textContent).toContain('rgw: 1');
- });
-
it('should test if host facts are transformed correctly if orch available', () => {
const features = [OrchestratorFeature.HOST_FACTS];
const payload = [
},
'cpu_count': 1,
'memory_total_kb': 1024,
- 'services': [],
- 'service_instances': [{'type': 'mon', 'count': 1}]
+ 'services': []
}, {
'hostname': 'host-1',
'sources': {
},
'cpu_count': 2,
'memory_total_kb': 1024,
- 'services': [],
- 'service_instances': [{'type': 'mon', 'count': 1}]
+ 'services': []
}]
# test with orchestrator available
with patch_orch(True, hosts=hosts_without_facts) as fake_client:
return [hosts_facts[0]]
return [hosts_facts[1]]
fake_client.hosts.get_facts.side_effect = get_facts_mock
- # test with ?facts=true
- self._get('{}?facts=true'.format(self.URL_HOST), version=APIVersion(1, 3))
+ # test with ?facts=true (explicitly disable service_instances)
+ self._get(
+ '{}?facts=true&include_service_instances=false'.format(self.URL_HOST),
+ version=APIVersion(1, 3)
+ )
self.assertStatus(200)
self.assertHeader('Content-Type',
APIVersion(1, 3).to_mime_type())
APIVersion(1, 3).to_mime_type())
self.assertJsonBody(hosts_without_facts)
+ def test_host_list_include_service_instances_flag(self):
+
+ orch_hosts = [
+ HostSpec('host-0'),
+ HostSpec('host-1')
+ ]
+
+ host0_daemons = [
+ DaemonDescription(hostname='host-0', daemon_type='mon', daemon_id='a'),
+ ]
+ host1_daemons = [
+ DaemonDescription(hostname='host-1', daemon_type='mon', daemon_id='a'),
+ DaemonDescription(hostname='host-1', daemon_type='mon', daemon_id='b'),
+ ]
+
+ with patch_orch(True, hosts=orch_hosts) as fake_client:
+ def list_daemons_mock(hostname=None, **_kwargs):
+ if hostname == 'host-0':
+ return host0_daemons
+ if hostname == 'host-1':
+ return host1_daemons
+ return []
+
+ fake_client.services.list_daemons.side_effect = list_daemons_mock
+ # include_service_instances=true should include expected counts
+ self._get(f'{self.URL_HOST}?include_service_instances=true', version=APIVersion(1, 3))
+ self.assertStatus(200)
+ body = self.json_body()
+ self.assertEqual(len(body), 2)
+ by_host = {h['hostname']: h for h in body}
+ self.assertIn('service_instances', by_host['host-0'])
+ self.assertIn('service_instances', by_host['host-1'])
+ self.assertEqual(by_host['host-0']['service_instances'], [{'type': 'mon', 'count': 1}])
+ self.assertEqual(by_host['host-1']['service_instances'], [{'type': 'mon', 'count': 2}])
+
+ # include_service_instances=false should omit service_instances
+ self._get(f'{self.URL_HOST}?include_service_instances=false', version=APIVersion(1, 3))
+ self.assertStatus(200)
+ body = self.json_body()
+ by_host = {h['hostname']: h for h in body}
+ self.assertNotIn('service_instances', by_host['host-0'])
+ self.assertNotIn('service_instances', by_host['host-1'])
+
+ # facts=true and include_service_instances=true
+ def get_facts_mock(hostname: str):
+ return [{
+ 'hostname': hostname,
+ 'cpu_count': 1 if hostname == 'host-0' else 2,
+ 'memory_total_kb': 1024
+ }]
+
+ fake_client.hosts.get_facts.side_effect = get_facts_mock
+ self._get(
+ f'{self.URL_HOST}?facts=true&include_service_instances=true',
+ version=APIVersion(1, 3)
+ )
+ self.assertStatus(200)
+ body = self.json_body()
+ by_host = {h['hostname']: h for h in body}
+ self.assertIn('service_instances', by_host['host-0'])
+ self.assertIn('service_instances', by_host['host-1'])
+ self.assertIn('cpu_count', by_host['host-0'])
+ self.assertIn('cpu_count', by_host['host-1'])
+
def test_get_1(self):
mgr.list_servers.return_value = []