docs: def unlock(path,
             zk_hosts=None,  # in case you need to unlock without having run lock (failed execution for example)
             identifier=None,
             max_concurrency=1,
             ephemeral_lease=False,
             scheme=None,
             profile=None,
             username=None,
             password=None,
             default_acl=None
             ):
      '''
      Remove lease from semaphore
  
      path
          The path in zookeeper where the lock is
  
      zk_hosts
          zookeeper connect string
  
      identifier
          Name to identify this minion, if unspecified defaults to hostname
  
      max_concurrency
          Maximum number of lock holders
  
      timeout
          timeout to wait for the lock. A None timeout will block forever
  
      ephemeral_lease
          Whether the locks in zookeper should be ephemeral
  
      Example:
  
      .. code-block: bash
  
          salt minion zk_concurrency.unlock /lock/path host1:1234,host2:1234
      '''
      # if someone passed in zk_hosts, and the path isn't in __context__['semaphore_map'], lets
      # see if we can find it
      zk = _get_zk_conn(profile=profile, hosts=zk_hosts, scheme=scheme,
                        username=username, password=password, default_acl=default_acl)
      if path not in __context__['semaphore_map']:
          __context__['semaphore_map'][path] = _Semaphore(zk, path, identifier,
                                                          max_leases=max_concurrency,
                                                          ephemeral_lease=ephemeral_lease)
  
      if path in __context__['semaphore_map']:
          __context__['semaphore_map'][path].release()
          del __context__['semaphore_map'][path]
          return True
      else:
          logging.error('Unable to find lease for path %s', path)
          return False