docs: def Services(core, vent=True, external=False, **kargs):
      """
      Get services that have exposed ports, expects param core to be True or
      False based on which type of services to return, by default limit to vent
      containers and processes not running externally, if not limited by vent
      containers, then core is ignored.
      """
      services = []
      path_dirs = PathDirs(**kargs)
      template = Template(template=path_dirs.cfg_file)
      services_uri = template.option('main', 'services_uri')
      try:
          # look for internal services
          if not external:
              d_client = docker.from_env()
              if vent:
                  c_filter = {'label': 'vent'}
                  containers = d_client.containers.list(filters=c_filter)
              else:
                  containers = d_client.containers.list()
              for c in containers:
                  uris = {}
                  name = None
                  if vent and 'vent.name' in c.attrs['Config']['Labels']:
                      if ((core and
                           'vent.groups' in c.attrs['Config']['Labels'] and
                           'core' in c.attrs['Config']['Labels']['vent.groups']) or
                          (not core and
                           'vent.groups' in c.attrs['Config']['Labels'] and
                           'core' not in c.attrs['Config']['Labels']['vent.groups'])):
                          name = c.attrs['Config']['Labels']['vent.name']
                          if name == '':
                              name = c.attrs['Config']['Labels']['vent.namespace'].split(
                                  '/')[1]
                          for label in c.attrs['Config']['Labels']:
                              if label.startswith('uri'):
                                  try:
                                      val = int(label[-1])
                                      if val not in uris:
                                          uris[val] = {}
                                      uris[val][label[:-1]
                                                ] = c.attrs['Config']['Labels'][label]
                                  except Exception as e:  # pragma: no cover
                                      logger.error('Malformed services section'
                                                   ' in the template file '
                                                   + str(e))
                  else:
                      name = c.name
                  if name and 'vent.repo' in c.attrs['Config']['Labels']:
                      name = c.attrs['Config']['Labels']['vent.repo'].split(
                          '/')[-1] + ': ' + name
                  ports = c.attrs['NetworkSettings']['Ports']
                  p = []
                  port_num = 1
                  for port in ports:
                      if ports[port]:
                          try:
                              service_str = ''
                              if 'uri_prefix' in uris[port_num]:
                                  service_str += uris[port_num]['uri_prefix']
                              host = ports[port][0]['HostIp']
                              if services_uri[0] and host == '0.0.0.0':
                                  host = services_uri[1]
                              service_str += host + ':'
                              service_str += ports[port][0]['HostPort']
                              if 'uri_postfix' in uris[port_num]:
                                  service_str += uris[port_num]['uri_postfix']
                              uri_creds = ''
                              if 'uri_user' in uris[port_num]:
                                  uri_creds += ' user:'
                                  uri_creds += uris[port_num]['uri_user']
                              if 'uri_pw' in uris[port_num]:
                                  uri_creds += ' pw:'
                                  uri_creds += uris[port_num]['uri_pw']
                              if uri_creds:
                                  service_str += ' - (' + uri_creds + ' )'
                              p.append(service_str)
                          except Exception as e:  # pragma: no cover
                              logger.info('No services defined for ' + str(name) + ' with exposed port ' +
                                          str(port_num) + ' because: ' + str(e))
                          port_num += 1
                  if p and name:
                      services.append((name, p))
                      logger.info(services)
          # look for external services
          else:
              ext_tools = template.section('external-services')[1]
              for ext_tool in ext_tools:
                  try:
                      name = ext_tool[0].lower()
                      p = []
                      settings_dict = json.loads(ext_tool[1])
                      if ('locally_active' in settings_dict and
                              settings_dict['locally_active'] == 'no'):
                          # default protocol to display will be http
                          protocol = 'http'
                          ip_address = ''
                          port = ''
                          for setting in settings_dict:
                              if setting == 'ip_address':
                                  ip_address = settings_dict[setting]
                              if setting == 'port':
                                  port = settings_dict[setting]
                              if setting == 'protocol':
                                  protocol = settings_dict[setting]
                          p.append(protocol + '://' + ip_address + ':' + port)
                      if p and name:
                          services.append((name, p))
                  except Exception:  # pragma: no cover
                      p = None
      except Exception as e:  # pragma: no cover
          logger.error('Could not get services ' + str(e))
      return services