Como gerenciar o Python em um ambiente restrito?

2

A necessidade:

  • Ofereça suporte a centenas de desenvolvedores Python e / ou prod servers que executam o código Python em um ambiente altamente restritivo.
  • Ser capaz de fornecer qualquer módulo compatível encontrado no PyPi.org que um desenvolvedor precise.

Ambiente:

  • Sem acesso externo.
  • Rede interna disponível.
  • Suporta várias plataformas (Windows, Linux, Apple)
  • Boa parte dos desenvolvedores e / ou servidores de prod não tem acesso a ferramentas de compilação.
  • No mínimo, suporta o mais recente Python 2.7 e Python 3.x

A pergunta:

  • Como alguém fornece suporte para a distribuição da instalação de módulos Python?
  • Como se lida com esses módulos do Python que exigem compilação? Lembre-se, muitas caixas não terão as ferramentas de compilação disponíveis.

Defina soluções valiosas com base em experiências semelhantes no mundo real.

Suposições:

  • Suponha que exista um processo mágico que autoriza os módulos a serem puxados para a rede interna para distribuição.
  • Não que o Anaconda não possa fazer parte da resposta, apenas certifique-se de abordar como você trabalharia com os pacotes do PyPi.org não encontrados lá.

Esclarecimentos:

  • Contêineres Docker são permitidos.
por Jay Soyer 12.06.2018 / 21:07

2 respostas

1

Prefácio

Hoje em dia, existem muitas opções viáveis para hospedar um repositório PyPI. Existem muitos pacotes disponíveis que implementam um servidor de repo PyPI, sendo os mais notáveis:

Existem também outros pacotes, mais ou menos exóticos, como PyPICloud , que carrega arquivos de pacotes diretamente para a instância do Amazon S3. . O Artifactory do JFrog também suporta pacotes python, embora não em edição livre, então só faz sentido se você já está pagando por uma licença. Você pode até criar um repositório local do PyPI usando nada além do stdlib do python, veja minha resposta no SO .

Além disso, este tópico foi discutido várias vezes sobre o SO, com as perguntas mais populares sendo Como criar meu próprio pypi? e < a href="https://stackoverflow.com/questions/18052217"> como criar o índice de repositório pypi local próprio sem espelho? Cuidado com o fato de a primeira pergunta ser bastante antiga e conter principalmente respostas desatualizadas, sendo a segunda mais atualizado.

devpi

No meu trabalho, avaliamos as soluções disponíveis há dois anos e estamos aderindo a devpi desde então. Desenvolvido pelas mesmas pessoas que estão por trás da popular ferramenta de teste pytest e da ferramenta de automação de tarefas de CI tox , devpi é uma ferramenta versátil que:

  • pode hospedar vários repositórios (chamados de índices), permitindo agrupar o acesso ao pacote;
  • age como um espelho PyPI por padrão, isso pode ser desativado por demanda;
  • fornece um controle de acesso baseado em função para o upload de pacotes;
  • oferece uma interface de usuário da web opcional que pode ser personalizada por meio do modelo de página;
  • oferece replicação do servidor principal - todas as réplicas sincronizarão automaticamente a base de pacotes do mestre nas alterações;
  • pode hospedar a documentação do pacote (Sphinx);
  • pode acionar a execução de teste no upload do pacote e exibir os resultados da execução de teste se conectado ao servidor de IC, como o Jenkins;
  • tem uma API de plug-in para estender no servidor e no cliente CLI (com base na biblioteca pluggy ; a mesma usada para estender tox ou pytest se você estiver familiarizado com eles); Você pode personalizar muitas coisas escrevendo seus próprios plugins, da autenticação aos backends de armazenamento. Existem também vários plugins internos disponíveis na página do Github .

O recurso mais poderoso da IMO são os índices. Um índice define um conjunto de pacotes que podem ser instalados a partir do URL do índice. Por exemplo, imagine uma única devpi instance com dois índices configurados: index foo oferece pacote A e índice bar oferece B . Agora você tem dois URLs de repositório:

$ pip install A --index-url=https://my.pypi.org/foo

será bem-sucedido, mas

$ pip install A --index-url=https://my.PyPI.org/bar

falhará. Os índices podem herdar um ao outro no sentido de estender a própria base de pacote, portanto, se bar herdar foo , você poderá instalar os dois A e B de bar index.

Isso nos permite configurar facilmente uma política de restrição de pacotes: digamos que temos dois grupos principais de usuários (devs e QA), cada grupo com seu próprio conjunto de pacotes necessários, também desenvolvemos pacotes oferecidos aos clientes e ferramentas para interna usar. Não há problema em agrupá-los com índices:

root/pypi
├── company/base    <- contains common packages like pip or setuptools
│   └── company/internal    <- in-house tools
│       ├── company/dev    <- packages necessary for development
│       │   ├── developer/sandbox    <- private index for single developer
│       │   └── developer2/sandbox
│       └── company/qa    <- packages for QA (test automation etc)
└── customer/release    <- customer packages

Agora, por exemplo, o desenvolvedor configura o URL de índice https://my.pypi.org/developer/sandbox uma vez e tem acesso a todos os novos pacotes enviados para, por exemplo. company/base , enquanto o cliente configura o URL de índice https://my.pypi.org/customer/release , não podendo acessar nenhum pacote de company/internal .

O root/pypi é um meta-índice especial: está sempre presente; se um índice o herda, todas as solicitações para instalar pacotes que não estão contidos no índice são intermediadas por proxy para pypi.org. Para desativar o espelhamento pypi.org, simplesmente não herde de root/pypi .

A política de restrição de uploads também é fácil de configurar por índice: todos os desenvolvedores podem fazer o upload para seus próprios sandboxes privados e company/dev ; todos os QAs podem fazer upload para company/qa ; somente admin pode fazer o upload para company/base , fazer o upload para company/internal e os índices do cliente são feitos pelo servidor de IC em compilações noturnas bem-sucedidas.

Consulte devpi docs para todo o processo de instalação e configuração; os documentos são bastante extensos e cobrem a maioria das questões que surgirão.

    
por 10.07.2018 / 14:10
1

Rodas personalizadas com extensões C compiladas

Isso é diferente de trivial e pode trazer muitas dores de cabeça quando feito de forma errada. Eu nunca vi uma solução totalmente ou pelo menos parcialmente automatizada para construir rodas a partir de dists de origem, devido ao diferente conjunto de dependências que cada pacote possui. A dificuldade de configurar um ambiente de construção também varia dependendo da plataforma - configurar docker em uma máquina Linux / MacOS e executar um script mais ou menos predefinido é muito mais fácil do que configurar o compilador Visual C ++ e criar ferramentas no Windows. / p>

Embora suportemos o Windows, precisamos de muito menos pacotes pré-compilados para o Windows do que o Linux; a maioria das rodas pré-compiladas são instaladas em jessie-slim containers que simplesmente não possuem gcc e material disponível. Desta forma, nós não incham os recipientes (razão principal para todo o penugem!). Todo o edifício está sendo feito manualmente, seguindo os exemplos existentes. Em uma construção bem-sucedida, o desenvolvedor é incentivado a copiar o log do terminal para uma essência, aprimorando a coleção de exemplos.

manylinux1_x86_64 / manylinux1_i686

Mantemos uma lista de receitas para as rodas vinculadas estaticamente que alguém criou com êxito; a abordagem básica é sempre a mesma:

  1. Executar limpo quay.io/pypa/manylinux1_x86_64 container
  2. Clone o código-fonte
  3. Instale as dependências necessárias
  4. Executar bdist_wheel
  5. Reparar as rodas com auditwheel
  6. Instalar a roda
  7. Execute os testes; recipiente de saída
  8. Se a criação e os testes forem bem-sucedidos, execute devpi upload nas rodas reparadas

Exemplo de receita para mysqlclient , constrói rodas para python 3.5 e python 3.6:

$ mkdir io
$ docker pull quay.io/pypa/manylinux1_x86_64
$ docker run --rm -w /root -v $(pwd)/io:/io -it quay.io/pypa/manylinux1_x86_64 /bin/bash
# yum install -y mysql-devel  # mysqlclient needs mysql-devel libs
# git clone https://github.com/PyMySQL/mysqlclient-python.git
# cd mysqlclient-python
# /opt/python/cp35-cp35m/bin/python setup.py bdist_wheel
# /opt/python/cp36-cp36m/bin/python setup.py bdist_wheel
# find dist/ -type f -name "*.whl" | xargs -I {} auditwheel repair {} -w /io
# # start the server for tests
# yum install mysql-server
# chkconfig mysqld on
# service mysqld start
# mysql for CentOS 5 is too old, use utf8 instead of utf8mb4 and hope for the best
# mysql -e 'create database mysqldb_test charset utf8;'
# sed -i '' 's/utf8mb4/utf8/' tests/travis.cnf
# # run the tests with built wheels
# find /io -name "*cp35*" | xargs -I {} /opt/python/cp35-cp35m/bin/python -m pip install {} pytest mock
# TESTDB=travis.cnf /opt/python/cp35-cp35m/bin/python -m pytest
# # same for py3.6
# find /io -name "*cp36*" | xargs -I {} /opt/python/cp36-cp36m/bin/python -m pip install {} pytest mock
# TESTDB=travis.cnf /opt/python/cp36-cp36m/bin/python -m pytest
# exit
$ # check the terminal log for any errors!
$ devpi login admin
$ devpi use https://my.pypi.org/company/base
$ devpi upload --from-dir=io/

Windows

Configuramos uma VM do Windows configurada para construção de rodas, com ferramentas de criação do Visual C ++, etc. Assim como no Linux, temos exemplos que descrevem passo a passo o que precisa ser feito para construir. No entanto, raramente é usado para a construção de rodas e serve principalmente como um escravo Jenkins.

    
por 10.07.2018 / 15:07

Tags