Por: @felipefc, @brunaoliveira
Publicado em: 2018-07-17

SDK Python

Durante o desenvolvimento dos produtos da iTFLEX, uma das etapas mais custosas é a realização dos testes da API. A causa é a ausência de testes desta parte, tornando o processo de testes manual e, em casos, demorado. Geralmente são utilizadas ferramentas como CURL e Postman, principalmente em funcionalidades onde o front-end não está disponível. Além disso, outro ponto de dificuldade encontrado hoje está na integração entre os produtos e por aplicações de terceiros.

Levando em conta esses empecilhos, foi realizada uma pesquisa e preparação para o desenvolvimento do Kit de Desenvolvimento de Software (SDK) dos produtos iTFLEX. O intuito é desenvolver uma ferramenta que possibilite a agilização dos testes e a integração dos produtos. Os principais impactos estarão relacionados com:

  • implementar testes das APIs;
  • melhorar o provisionamento dos dispositivos;
  • facilitar a criação de scripts de população;
  • facilitar a integração dos sistemas dos clientes.

A Pesquisa

Na etapa de pesquisa foi observado principalmente a estruturação dos SDKs. Outros pontos observados foram:

  • formas de realizar e manter a autenticação;
  • gestão de diversos recursos.

Ao todo, foram analizados três principais SDKs brevemente descritos a seguir.

Github: PyGithub

O SDK em Python do Github, PyGithub, abrange os recursos comuns para os usuários do sistema: repositórios, Commits, PullRequets, gerenciamento de times, etc. No entanto, embora tenha diversos recursos, tudo gira em torno de um único produto. Para o consumidor do SDK, tudo é feito à partir de uma instância da classe Github. Como no exemplo abaixo:

from github import Github

github = Github("username", "password")

for repo in github.get_user().get_repos()
    print(repo.name)

A criação de items não é feita com objetos, mas através da passagem de parâmetros. Por exemplo:

milestone = repository.create_milestone(
    "My-Milestone-01",
    description="Milestone description"
)

Quanto à organização dos arquivos que compõe o SDK, tudo está disposto no mesmo diretório. Embora seja muito bem documentado, ao projetar o nosso cenário com vários produtos organizados em vários serviços, tivemos que pensar em algo menos agrupado.

AWS boto3

O SDK da AWS, boto3, permite o gerenciamento de alguns dos produtos da Amazon, sendo eles: a plataforma de armazenamento S3, o banco de dados DynamoDB e o EC2. Essa distinção de recursos/produtos se assemelha mais à nossa necessidade. Um contraponto do boto3 é que a forma de autenticação foge do padrão visualizado nos demais SDK. É preciso ter o cli da Amazon instalado para configurar as credenciais.

O uso da ferramenta é simples, por exemplo uma listagem:

import boto3

s3 = boto3.resource("s3")

bucket = s3.Bucket("my-bucket")

for item in bucket.objects.all():
    print(item.key)

É válido ressaltar que os arquivos estão organizados por recurso. Isto é, o diretório raíz contém os arquivos de classes comuns (como Exceptions, Authentication, etc.), enquanto que as classes específicas dos recursos estão em diretórios distintos.

Dropbox SDK Python

O Dropbox SDK em Python, também mantém um padrão similar no uso da ferramenta. Talvez a maior diferença para o usuário do SDK é que sua autenticação é feita somente via ACCESS_TOKEN, que deve ser habilitado através do próprio Dropbox. Como no exemplo abaixo:

import dropbox

dbx = dropbox.Dropbox("ACCESS_TOKEN")

# Verificar usuário autenticado pelo Token
dbx.users_get_current_account()

# Uso
for entry in dbx.files_list_folder("").entries:
    print(entry.name)

Assim como o Github, não há separação de arquivos por recursos visto que tudo compõe apenas um produto.

Outros SDKs

Solução Proposta

Após a etapa de pesquisa, foi discutida uma solução baseada na implementação dos SDKS pesquisados, seguindo alguns conceitos interessantes como:

  • autenticação flexível: via usuário e senha ou via chave de integração;
import itflex

pyflex = itflex.PyFlex("username", "password")
# ou
pyflex = itflex.PyFlex("AIo90e09OAKFLA012OiiJIwsj150e54ylvlaWEOiooak4")

A autenticação via ACCESS_TOKEN é a mais adequada. Devido à lógica de refresh nos Tokens obtidos via usuário e senha, a autenticação por esse meio não é a recomendável para utilização do SDK por longos períodos de tempo.

  • manipulação dos dados através de objetos. Por exemplo:
import itflex

user = itflex.core.types.User()
site = itflex.cdm.types.Site()
router = itflex.cdm.types.Router()
cas = itflex.vpnflex.types.Cas()
cert = itflex.vpnflex.types.Cert()

Uso do SDK

Criação

A criação pode ser feita de duas formas:

  • Passando os dados como parâmetros para o método create_<type> do recurso
pyflex.core.create_user(
    username="walterhw",
    password="heisenberg52",
    fullname="Walter Hartwell White"
)
  • Passando um objeto para o método create_<type> do recurso
new_user = itflex.core.types.User()
new_user.username = "walterhw"
new_user.password = "heisenberg52"
new_user.fullname = "Walter Hartwell White"

pyflex.core.create_user(new_user)

Busca

user = pyflex.core.get_user(id="Ayk6UuMqBeZ9KxkaXZynt")

Atualização

A atualização segue a flexibilidade do método create. É possível realizar a operação em três formas:

  • Atualizando diretamente pelo objeto
user = pyflex.core.get_user(id="Ayk6UuMqBeZ9KxkaXZynt")

# `user` é um objeto <pyflex.core.types.User object>
# então...

user.update(
  username="walterwhite",
  email="walterwhite@abq.us"
)
  • Passando os dados como parâmetros para o método update_<type> do recurso
pyflex.core.update_user(
  id="Ayk6UuMqBeZ9KxkaXZynt",
  username="walterwhite",
  email="walterwhite@abq.com"
)
  • Passando um objeto para o método update_<type> do recurso
modified_user = itflex.core.types.User()
modified_user.username = "walterwhite"
modified_user.email = "walterwhite@abq.com"

pyflex.core.update_user(modified_user)

Remoção

  • Removendo pelo objeto
user = pyflex.core.get_user(id="Ayk6UuMqBeZ9KxkaXZynt")
user.delete()
  • Removendo pelo método delete_<type> do recurso
pyflex.core.delete_user(id="Ayk6UuMqBeZ9KxkaXZynt")

Listagem

users = pyflex.core.list_users()