在 CI 作业中解析 .netrc 以访问 GitLab PyPI 包注册表时出现 EOFError

问题描述 投票:0回答:1

我在存储库 A 中有一个 CI 作业,用于构建图像(

Dockerfile
,通过 Kaniko),这需要来自存储库 B 的包存储库中的包。

由于这是一项将来会重复进行的任务,因此我创建了一个名为 CI_GROUP_API 的 GAT(组访问令牌,权限:api,角色:

Developer
),以及相应的组 CICD 变量,该变量具有相同的值名称和值,以便我的 CI 作业可以使用它访问该组中的所有其他存储库。

我在 CI 工作中使用 GAT 动态生成

.netrc
,并且我还在调整我的
requirements.txt
以添加包(将使此更改在将来永久存在)。 CI作业所需的文件可以在下面的错误日志后看到。当我运行我的工作时,我收到:

Requirement already satisfied: pip in /usr/local/lib/python3.10/site-packages (24.0)
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Looking in indexes: https://gitlab.company.com/api/v4/projects/58838/packages/pypi/simple
User for gitlab.company.com: ERROR: Exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/cli/base_command.py", line 180, in exc_logging_wrapper
    status = run_func(*args)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/cli/req_command.py", line 245, in wrapper
    return func(self, options, args)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/commands/install.py", line 377, in run
    requirement_set = resolver.resolve(
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 95, in resolve
    result = self._result = resolver.resolve(
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py", line 546, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py", line 397, in resolve
    self._add_to_criteria(self.state.criteria, r, parent=None)
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py", line 173, in _add_to_criteria
    if not criterion.candidates:
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/resolvelib/structs.py", line 156, in __bool__
    return bool(self._sequence)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 155, in __bool__
    return any(self)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 143, in <genexpr>
    return (c for c in iterator if id(c) not in self._incompatible_ids)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 44, in _iter_built
    for version, func in infos:
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 297, in iter_index_candidate_infos
    result = self._finder.find_best_candidate(
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/package_finder.py", line 890, in find_best_candidate
    candidates = self.find_all_candidates(project_name)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/package_finder.py", line 831, in find_all_candidates
    page_candidates = list(page_candidates_it)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/sources.py", line 194, in page_candidates
    yield from self._candidates_from_page(self._link)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/package_finder.py", line 791, in process_project_url
    index_response = self._link_collector.fetch_response(project_url)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/collector.py", line 461, in fetch_response
    return _get_index_content(location, session=self.session)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/collector.py", line 364, in _get_index_content
    resp = _get_simple_response(url, session=session)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/index/collector.py", line 135, in _get_simple_response
    resp = session.get(
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/requests/sessions.py", line 602, in get
    return self.request("GET", url, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/network/session.py", line 520, in request
    return super().request(method, url, *args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/requests/sessions.py", line 710, in send
    r = dispatch_hook("response", hooks, r, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/pip/_vendor/requests/hooks.py", line 30, in dispatch_hook
    _hook_data = hook(hook_data, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/network/auth.py", line 500, in handle_401
    username, password, save = self._prompt_for_password(parsed.netloc)
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/network/auth.py", line 455, in _prompt_for_password
    username = ask_input(f"User for {netloc}: ") if self.prompting else None
  File "/usr/local/lib/python3.10/site-packages/pip/_internal/utils/misc.py", line 251, in ask_input
    return input(message)
EOFError: EOF when reading a line
error building image: error building stage: failed to execute command: waiting for process to exit: exit status 2

我的 CI 工作定义如下:

build-service:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: ['']
  tags:
    - asprunner
  rules:
    # Build base image only if the Dockerfile or CICD config file have changed and been pushed to the cloud branch
    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "dev"'
      when: on_success
  script:
    - echo "Building image for service X using Kaniko"
    - |
      export BASE_REGISTRY_URL=registry.gitlab.company.com/mygroup/base-service
      export BASE_TOKEN_NAME=CI_GROUP_API
      export BASE_TOKEN_VALUE=$CI_GROUP_API

      cat <<EOT >> .netrc
      machine gitlab.company.com
      login $BASE_TOKEN_NAME
      password $BASE_TOKEN_VALUE
      EOT

      cat <<EOT >> requirements.txt
      --index-url https://gitlab.company.com/api/v4/projects/58838/packages/pypi/simple
      base-service
      
      EOT

      echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_JOB_TOKEN}" | base64 | tr -d '\n')\"},\"${BASE_REGISTRY_URL}\":{\"username\":\"${BASE_TOKEN_NAME}\",\"password\":\"${BASE_TOKEN_VALUE}\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor
       --context .
       --dockerfile Dockerfile
       --insecure
       --skip-tls-verify
       --skip-tls-verify-pull
       --insecure-pull
       --destination "${CI_REGISTRY_IMAGE}:v0.2"

我对应的

Dockerfile
可以在下面看到:

FROM registry.company.com/mygroup/base-service:v1.0
ENV DEBIAN_FRONTEND noninteractive

COPY ./requirements.txt requirements.txt
COPY ./.netrc .netrc
RUN echo "----------- requirements.txt -----------" && cat requirements.txt 
RUN echo "----------- .netrc -----------" && cat .netrc
RUN pip3 install --upgrade pip && pip3 install --no-cache -r requirements.txt

RUN mkdir -p service
COPY main.py service/
COPY gltf_transformer service/

RUN rm requirements.txt .netrc

ENTRYPOINT ["sh", "python3 main.py"]

生成的

pip
相关文件如下所示:

需求.txt

pygltflib
--index-url https://gitlab.company.com/api/v4/projects/58838/packages/pypi/simple
x-base-service

.netrc

---------- .netrc -----------

machine gitlab.company.com
login CI_GROUP_API
password [MASKED]

我认为

[MASKED]
(GitLab 在 CI 作业日志中隐藏屏蔽变量的方式)可能已作为实际值写入
.netrc
。然而,首先在读取用户时出现错误,其次我添加了

文物: 路径: - 要求.txt - .netrc 何时:on_failure

我的工作是获取文件并验证令牌的值是否存在。

我还将这两个文件本地下载到我的系统,并使用作业工件中的

requirements.txt
运行 pip 来获取
.netrc
。效果很好。

python gitlab continuous-integration .netrc
1个回答
0
投票

错误消息非常非常不准确。

首先我需要澄清,它在本地工作的唯一原因是因为

pip
正在使用我的 SSH 连接到软件包存储库,而
.netrc
实际上从未使用过。当我在干净的环境中使用
pip
文件运行
requirements.txt
时,我发现了这一点,它要求我提供使用的名称和密码。

我的下一个想法是编码才是问题所在。毕竟文档指出:

[.netrc documentation on non-ASCII characters1

但是,使用

iconv
将 UTF-8 转换为 ASCII 没有执行任何操作,错误仍然存在。

然后我在第N次阅读文档时想起来,

.netrc
与特定用户相关。现在,在 Docker 容器内,我们实际上没有用户,但是我们确实有
/root
目录作为主目录。

我添加了

COPY ./.netrc /root/.netrc

到我的 Dockerfile,然后修复引用该文件的所有以下路径并且它起作用了。

© www.soinside.com 2019 - 2024. All rights reserved.