summaryrefslogtreecommitdiff
path: root/gitlab/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'gitlab/client.py')
-rw-r--r--gitlab/client.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/gitlab/client.py b/gitlab/client.py
index c1e0825..b791c8f 100644
--- a/gitlab/client.py
+++ b/gitlab/client.py
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Wrapper for the GitLab API."""
+import os
import time
from typing import Any, cast, Dict, List, Optional, Tuple, TYPE_CHECKING, Union
@@ -256,6 +257,87 @@ class Gitlab(object):
retry_transient_errors=config.retry_transient_errors,
)
+ @classmethod
+ def merge_config(
+ cls,
+ options: dict,
+ gitlab_id: Optional[str] = None,
+ config_files: Optional[List[str]] = None,
+ ) -> "Gitlab":
+ """Create a Gitlab connection by merging configuration with
+ the following precedence:
+
+ 1. Explicitly provided CLI arguments,
+ 2. Environment variables,
+ 3. Configuration files:
+ a. explicitly defined config files:
+ i. via the `--config-file` CLI argument,
+ ii. via the `PYTHON_GITLAB_CFG` environment variable,
+ b. user-specific config file,
+ c. system-level config file,
+ 4. Environment variables always present in CI (CI_SERVER_URL, CI_JOB_TOKEN).
+
+ Args:
+ options: A dictionary of explicitly provided key-value options.
+ gitlab_id: ID of the configuration section.
+ config_files: List of paths to configuration files.
+ Returns:
+ (gitlab.Gitlab): A Gitlab connection.
+
+ Raises:
+ gitlab.config.GitlabDataError: If the configuration is not correct.
+ """
+ config = gitlab.config.GitlabConfigParser(
+ gitlab_id=gitlab_id, config_files=config_files
+ )
+ url = (
+ options.get("server_url")
+ or config.url
+ or os.getenv("CI_SERVER_URL")
+ or gitlab.const.DEFAULT_URL
+ )
+ private_token, oauth_token, job_token = cls._merge_auth(options, config)
+
+ return cls(
+ url=url,
+ private_token=private_token,
+ oauth_token=oauth_token,
+ job_token=job_token,
+ ssl_verify=options.get("ssl_verify") or config.ssl_verify,
+ timeout=options.get("timeout") or config.timeout,
+ api_version=options.get("api_version") or config.api_version,
+ per_page=options.get("per_page") or config.per_page,
+ pagination=options.get("pagination") or config.pagination,
+ order_by=options.get("order_by") or config.order_by,
+ user_agent=options.get("user_agent") or config.user_agent,
+ )
+
+ @staticmethod
+ def _merge_auth(options: dict, config: gitlab.config.GitlabConfigParser) -> Tuple:
+ """
+ Return a tuple where at most one of 3 token types ever has a value.
+ Since multiple types of tokens may be present in the environment,
+ options, or config files, this precedence ensures we don't
+ inadvertently cause errors when initializing the client.
+
+ This is especially relevant when executed in CI where user and
+ CI-provided values are both available.
+ """
+ private_token = options.get("private_token") or config.private_token
+ oauth_token = options.get("oauth_token") or config.oauth_token
+ job_token = (
+ options.get("job_token") or config.job_token or os.getenv("CI_JOB_TOKEN")
+ )
+
+ if private_token:
+ return (private_token, None, None)
+ if oauth_token:
+ return (None, oauth_token, None)
+ if job_token:
+ return (None, None, job_token)
+
+ return (None, None, None)
+
def auth(self) -> None:
"""Performs an authentication using private token.