mirror of https://github.com/interlegis/sigi.git
12 changed files with 961 additions and 600 deletions
@ -0,0 +1,2 @@ |
|||
class MultipleServicesReturned(Exception): |
|||
pass |
|||
@ -0,0 +1,389 @@ |
|||
import requests |
|||
import sys |
|||
from django.conf import settings |
|||
from django.utils import timezone |
|||
from django.utils.translation import gettext as _ |
|||
from django_extensions.management.jobs import DailyJob |
|||
from url_normalize import url_normalize |
|||
from sigi.apps.casas.models import Orgao, TipoOrgao |
|||
from sigi.apps.contatos.models import UnidadeFederativa |
|||
from sigi.apps.servicos import generate_instance_name, nomeia_instancias |
|||
from sigi.apps.servicos.exceptions import MultipleServicesReturned |
|||
from sigi.apps.servicos.models import Servico, LogServico, TipoServico |
|||
from sigi.apps.utils.management.jobs import AdminJobMixin |
|||
|
|||
|
|||
class Job(AdminJobMixin, DailyJob): |
|||
help = _("Atualiza registros de DNS") |
|||
|
|||
nomes_gerados = None |
|||
dados = None |
|||
|
|||
counter = 0 |
|||
ignorados = 0 |
|||
erros = 0 |
|||
updates = 0 |
|||
desativados = 0 |
|||
novos = 0 |
|||
|
|||
def __init__(self): |
|||
super().__init__() |
|||
self.nomes_gerados = { |
|||
generate_instance_name(o): o |
|||
for o in Orgao.objects.filter(tipo__legislativo=True) |
|||
} |
|||
|
|||
def execute(self): |
|||
if not self._retrieve_json_data(): |
|||
print(_("Processo abortado!"), file=sys.stderr) |
|||
return |
|||
|
|||
registros_ativos = Servico.objects.filter( |
|||
tipo_servico__modo=TipoServico.MODO_REGISTRO, data_desativacao=None |
|||
) |
|||
|
|||
nomeia_instancias( |
|||
servicos=registros_ativos.filter(instancia=""), |
|||
user=self.get_sys_user(), |
|||
) |
|||
|
|||
registros_ativos.update(flag_confirmado=False) |
|||
|
|||
total = len(self.dados) |
|||
self.erros = 0 |
|||
self.updates = 0 |
|||
self.desativados = 0 |
|||
self.novos = 0 |
|||
|
|||
print( |
|||
"\n\n", |
|||
_("Processando {total} registros recebidos").format(total=total), |
|||
"\n\n", |
|||
) |
|||
|
|||
for rec in self.get_dados(): |
|||
tipo_servico = self.get_tipo_servico(rec) |
|||
if not tipo_servico: |
|||
self.erros += 1 |
|||
continue |
|||
|
|||
try: |
|||
servico = self.get_registro(tipo_servico, rec) |
|||
except MultipleServicesReturned as e: |
|||
print("* ", str(e), file=sys.sys.stderr) |
|||
self.erros += 1 |
|||
continue |
|||
|
|||
if servico: |
|||
self.atualiza_registro(servico, rec) |
|||
continue |
|||
|
|||
# Tenta criar o registro |
|||
orgao = self.get_orgao(rec) |
|||
if not orgao: |
|||
self.erros += 1 |
|||
continue |
|||
|
|||
self.cria_registro(rec, tipo_servico, orgao) |
|||
self.novos += 1 |
|||
|
|||
# Desativar todos que não foram confirmados |
|||
nao_confirmados = registros_ativos.filter(flag_confirmado=False) |
|||
self.desativados += self.bulk_desativa(nao_confirmados) |
|||
|
|||
print("\n\n", _("TOTAIS")) |
|||
print("------", "\n") |
|||
print( |
|||
_(" * registros recebidos do webservice: {total}").format( |
|||
total=total |
|||
) |
|||
) |
|||
print( |
|||
_(" * registros ignorados..............: {ignorados}").format( |
|||
ignorados=self.ignorados |
|||
) |
|||
) |
|||
print( |
|||
_(" * registros com erro...............: {erros}").format( |
|||
erros=self.erros |
|||
) |
|||
) |
|||
print( |
|||
_(" * atualizações realizadas..........: {updates}").format( |
|||
updates=self.updates |
|||
) |
|||
) |
|||
print( |
|||
_(" * registros desativados............: {desativados}").format( |
|||
desativados=self.desativados |
|||
) |
|||
) |
|||
print( |
|||
_(" * novos registros criados..........: {novos}").format( |
|||
novos=self.novos |
|||
) |
|||
) |
|||
|
|||
def _retrieve_json_data(self): |
|||
if (not hasattr(settings, "REGISTRO_PATH")) or ( |
|||
not settings.REGISTRO_PATH |
|||
): |
|||
print( |
|||
_( |
|||
"Falta a configuração da URL de acesso aos registros de " |
|||
"DNS instalados" |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
print( |
|||
_("Buscando dados no webservice {wsentry}...").format( |
|||
wsentry=settings.REGISTRO_PATH |
|||
), |
|||
) |
|||
try: |
|||
response = requests.get(settings.REGISTRO_PATH) |
|||
except Exception as e: |
|||
print( |
|||
_("Ocorreu um erro ao acessar {url}: {error}").format( |
|||
url=settings.REGISTRO_PATH, error=str(e) |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if response.status_code != 200: |
|||
print( |
|||
_( |
|||
"Problemas na resposta do webservice de DNS: " |
|||
"{code} - {reason}" |
|||
).format(code=response.status_code, reason=response.reason), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if "json" not in response.headers["content-type"]: |
|||
print( |
|||
_("Tipo de conteúdo não é JSON: {contenttype}").format( |
|||
contenttype=response.headers["content-type"] |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
result = response.json() |
|||
|
|||
if result["tipo"] != "DNS": |
|||
print( |
|||
_("Tipo de resultado inesperado: {tipo}").format( |
|||
tipo=result["tipo"] |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if result["status"] != "ok": |
|||
print( |
|||
_( |
|||
"O webservice respondeu com status {status}: logs: {logs}" |
|||
).format(status=result["status"], logs=result["logs"]), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
self.dados = result["result"]["dominios"] |
|||
|
|||
return True |
|||
|
|||
def get_dados(self): |
|||
if self.dados is None: |
|||
if not self._retrieve_json_data(): |
|||
return |
|||
|
|||
self.ignorados = 0 |
|||
self.counter = 0 |
|||
|
|||
for record in self.dados: |
|||
self.counter += 1 |
|||
if ( |
|||
"interlegis" in record["url"].lower() |
|||
or "interlegis" in record["orgao"].lower() |
|||
): |
|||
self.ignorados += 1 |
|||
continue |
|||
yield record |
|||
|
|||
def get_tipo_servico(self, rec): |
|||
try: |
|||
tipo_servico = TipoServico.objects.get(tipo_rancher=rec["tipo"]) |
|||
except TipoServico.DoesNotExist: |
|||
print( |
|||
"* ", |
|||
_( |
|||
"Erro ao processar {counter}º registro. Tipo de " |
|||
"registro desconhecido: {tipo}. Registro: {r}" |
|||
).format(counter=self.counter, tipo=rec["tipo"], r=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return None |
|||
if tipo_servico.modo != TipoServico.MODO_REGISTRO: |
|||
print( |
|||
"* ", |
|||
_( |
|||
"O {counter}º registro de DNS {rec} indica um tipo de " |
|||
"serviço que não é de registro de DNS." |
|||
).format(counter=self.counter, rec=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return None |
|||
return tipo_servico |
|||
|
|||
def get_orgao(self, rec): |
|||
# tenta achar pelo órgão dado no registro |
|||
if rec["orgao"] in self.nomes_gerados: |
|||
return self.nomes_gerados[rec["orgao"]] |
|||
|
|||
# Senão, vamos buscar pelo nome do domínio na URL |
|||
|
|||
partes = rec["url"].split(".") |
|||
# A UF deve ser o 2º nível e o domínio, o último |
|||
uf = partes[-3] |
|||
dominio = partes[0].replace("https://", "") |
|||
|
|||
if not UnidadeFederativa.objects.filter(sigla=uf).exists(): |
|||
print( |
|||
"* ", |
|||
_( |
|||
"Impossível identificar o órgão dono do registro {url}, " |
|||
"no {counter}º registro: {rec}" |
|||
).format(url=rec["url"], counter=self.counter, rec=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return None |
|||
|
|||
nome_orgao = f"{dominio}-{uf}" |
|||
if nome_orgao in self.nomes_gerados: |
|||
return self.nomes_gerados[nome_orgao] |
|||
|
|||
return None |
|||
|
|||
def get_registro(self, tipo_servico, rec): |
|||
servicos = Servico.objects.filter( |
|||
tipo_servico=tipo_servico, |
|||
instancia=rec["orgao"], |
|||
data_desativacao=None, |
|||
).order_by("-data_ativacao") |
|||
if not servicos: |
|||
# Nenhum registro ativo, podemos criar um |
|||
return None |
|||
if len(servicos) == 1: |
|||
# Um único registro ativo, deve ser esse |
|||
return servicos[0] |
|||
# Mais de um registro ativo para este órgão. |
|||
# Não tem como decidir qual atualizar |
|||
raise MultipleServicesReturned( |
|||
_( |
|||
"Existem {qty} registros ativos para o órgão {orgao}. " |
|||
"Registro {r}" |
|||
).format(qty=len(servicos), orgao=rec["orgao"], r=rec) |
|||
) |
|||
|
|||
def atualiza_registro(self, registro, rec): |
|||
old = registro.url |
|||
new = rec["url"] |
|||
|
|||
if old != new: |
|||
registro.url = new |
|||
self.updates += 1 |
|||
log = _( |
|||
"A URL do {tipo} de {orgao} atualizado de {old} para {new}" |
|||
).format( |
|||
tipo=registro.tipo_servico.sigla, |
|||
orgao=registro.casa_legislativa.nome, |
|||
old=old, |
|||
new=new, |
|||
) |
|||
print("* ", log) |
|||
registro.logservico_set.create( |
|||
descricao=_("URL atualizada"), |
|||
data=timezone.localdate(), |
|||
log=log, |
|||
) |
|||
self.admin_log_change(registro, log) |
|||
registro.flag_confirmado = True |
|||
registro.save() |
|||
|
|||
def cria_registro(self, rec, tipo_servico, orgao): |
|||
registro = Servico( |
|||
casa_legislativa=orgao, |
|||
tipo_servico=tipo_servico, |
|||
url=rec["url"], |
|||
hospedagem_interlegis=rec["hospedagem"] == "Interlegis", |
|||
instancia=rec["orgao"], |
|||
data_ativacao=timezone.localdate(), |
|||
flag_confirmado=True, |
|||
) |
|||
registro.save() |
|||
registro.logservico_set.create( |
|||
descricao=_("Serviço criado no SEIT"), |
|||
data=timezone.localdate(), |
|||
log=_( |
|||
"Servico criado no SEIT e atualizado no SIGI " |
|||
"automaticamente pelo processo de CRON" |
|||
), |
|||
) |
|||
self.admin_log_addition( |
|||
registro, |
|||
_( |
|||
"Servico criado no SEIT e atualizado no SIGI " |
|||
"automaticamente pelo processo de CRON" |
|||
), |
|||
) |
|||
print( |
|||
"* ", |
|||
_("{servico} criado para {orgao}").format( |
|||
servico=registro.tipo_servico.nome, |
|||
orgao=registro.casa_legislativa.nome, |
|||
), |
|||
) |
|||
|
|||
def bulk_desativa(self, registros): |
|||
log_list = [ |
|||
LogServico( |
|||
servico=s, |
|||
descricao=_("Serviço desativado no SEIT"), |
|||
data=timezone.localdate(), |
|||
log=_( |
|||
"Desativado automaticamente pois não foi encontrado na " |
|||
"Infraestrutura do Interlegis" |
|||
), |
|||
) |
|||
for s in registros |
|||
] |
|||
LogServico.objects.bulk_create(log_list) |
|||
self.admin_log_change( |
|||
registros, |
|||
_( |
|||
"Desativado automaticamente pois não foi encontrado na " |
|||
"Infraestrutura do Interlegis" |
|||
), |
|||
) |
|||
print( |
|||
*[ |
|||
_( |
|||
"* {servico} de {orgao} desativado porque não consta nos " |
|||
"dados do webservice do SEIT\n" |
|||
).format( |
|||
servico=s.tipo_servico.nome, orgao=s.casa_legislativa.nome |
|||
) |
|||
for s in registros |
|||
], |
|||
) |
|||
return registros.update( |
|||
data_desativacao=timezone.localdate(), |
|||
motivo_desativacao=_( |
|||
"Desativado automaticamente pois não foi encontrado na " |
|||
"Infraestrutura do Interlegis" |
|||
), |
|||
) |
|||
@ -0,0 +1,474 @@ |
|||
from datetime import datetime |
|||
import requests |
|||
import sys |
|||
from django.conf import settings |
|||
from django.utils import timezone |
|||
from django.utils.formats import localize |
|||
from django.utils.translation import gettext as _ |
|||
from django_extensions.management.jobs import DailyJob |
|||
from url_normalize import url_normalize |
|||
from sigi.apps.servicos import generate_instance_name, nomeia_instancias |
|||
from sigi.apps.servicos.exceptions import MultipleServicesReturned |
|||
from sigi.apps.servicos.models import Servico, LogServico, TipoServico |
|||
from sigi.apps.casas.models import Orgao, TipoOrgao |
|||
from sigi.apps.utils import to_ascii |
|||
from sigi.apps.utils.management.jobs import AdminJobMixin |
|||
|
|||
|
|||
class Job(AdminJobMixin, DailyJob): |
|||
help = _("Sincronização dos Serviços SEIT na infraestrutura") |
|||
|
|||
UPDATE_NOTHING = None |
|||
UPDATE_DEACTIVATED = 0 |
|||
UPDATE_UPDATED = 1 |
|||
|
|||
UPDATABLE_FIELDS = ( |
|||
("url", "url"), |
|||
("versao", "version"), |
|||
) |
|||
|
|||
nomes_gerados = None |
|||
dados = None |
|||
|
|||
counter = 0 |
|||
ignorados = 0 |
|||
erros = 0 |
|||
updates = 0 |
|||
desativados = 0 |
|||
novos = 0 |
|||
|
|||
def __init__(self): |
|||
super().__init__() |
|||
self.nomes_gerados = { |
|||
generate_instance_name(o): o |
|||
for o in Orgao.objects.filter(tipo__legislativo=True) |
|||
} |
|||
|
|||
def execute(self): |
|||
if not self._retrieve_json_data(): |
|||
print(_("Processo abortado!"), file=sys.stderr) |
|||
return |
|||
|
|||
hospedagens_ativas = Servico.objects.filter( |
|||
tipo_servico__modo=TipoServico.MODO_HOSPEDAGEM, |
|||
data_desativacao=None, |
|||
).exclude(tipo_servico__tipo_rancher="") |
|||
|
|||
nomeia_instancias( |
|||
servicos=hospedagens_ativas.filter(instancia=""), |
|||
user=self.get_sys_user(), |
|||
) |
|||
|
|||
hospedagens_ativas.update(flag_confirmado=False) |
|||
|
|||
total = len(self.dados) |
|||
self.erros = 0 |
|||
self.updates = 0 |
|||
self.desativados = 0 |
|||
self.novos = 0 |
|||
|
|||
print( |
|||
"\n\n", |
|||
_("Processando {total} registros recebidos").format(total=total), |
|||
"\n\n", |
|||
) |
|||
|
|||
for rec in self.get_dados(): |
|||
tipo_servico = self.get_tipo_servico(rec) |
|||
if not tipo_servico: |
|||
self.erros += 1 |
|||
continue |
|||
|
|||
try: |
|||
servico = self.get_servico(tipo_servico, rec) |
|||
except MultipleServicesReturned as e: |
|||
print("* ", str(e), file=sys.stderr) |
|||
self.erros += 1 |
|||
continue |
|||
|
|||
if servico: |
|||
self.atualiza_servico(servico, rec) |
|||
continue |
|||
|
|||
# Tenta criar o serviço |
|||
orgao = self.get_orgao(rec) |
|||
if not orgao: |
|||
self.erros += 1 |
|||
continue |
|||
|
|||
self.cria_servico(rec, tipo_servico, orgao) |
|||
self.novos += 1 |
|||
|
|||
# Desativar todos que não foram confirmados |
|||
nao_confirmados = hospedagens_ativas.filter(flag_confirmado=False) |
|||
self.desativados += self.bulk_desativa(nao_confirmados) |
|||
|
|||
print("\n\n", _("TOTAIS")) |
|||
print("------", "\n\n") |
|||
print(" * registros recebidos do webservice: ", total) |
|||
print(" * registros ignorados..............: ", self.ignorados) |
|||
print(" * registros com erro...............: ", self.erros) |
|||
print(" * atualizações realizadas..........: ", self.updates) |
|||
print(" * serviços desativados.............: ", self.desativados) |
|||
print(" * novos serviços criados...........: ", self.novos) |
|||
|
|||
def _retrieve_json_data(self): |
|||
if (not hasattr(settings, "HOSPEDAGEM_PATH")) or ( |
|||
not settings.HOSPEDAGEM_PATH |
|||
): |
|||
print( |
|||
_( |
|||
"Falta a configuração da URL de acesso aos serviços " |
|||
"instalados" |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
print( |
|||
_("Buscando dados no webservice {wsentry}...").format( |
|||
wsentry=settings.HOSPEDAGEM_PATH |
|||
), |
|||
) |
|||
try: |
|||
response = requests.get(settings.HOSPEDAGEM_PATH) |
|||
except Exception as e: |
|||
print( |
|||
_("Ocorreu um erro ao acessar {url}: {error}").format( |
|||
url=settings.HOSPEDAGEM_PATH, |
|||
error=str(e), |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if response.status_code != 200: |
|||
print( |
|||
_( |
|||
"Problemas na resposta do webservice de serviços: " |
|||
"{code} - {reason}" |
|||
).format(code=response.status_code, reason=response.reason), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if not "json" in response.headers["content-type"]: |
|||
print( |
|||
_("Tipo de conteúdo não é JSON: {contenttype}").format( |
|||
contenttype=response.headers["content-type"] |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
result = response.json() |
|||
|
|||
if result["tipo"] != "SERVICES": |
|||
print( |
|||
_("Tipo de resultado inesperado: {tipo}").format( |
|||
tipo=result["tipo"] |
|||
), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if result["status"] != "ok": |
|||
print( |
|||
_( |
|||
"O webservice respondeu com status {status}: logs: {logs}" |
|||
).format(status=result["status"], logs=result["logs"]), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
self.dados = result["result"]["servicos"] |
|||
|
|||
return True |
|||
|
|||
def get_dados(self): |
|||
if self.dados is None: |
|||
if not self._retrieve_json_data(): |
|||
return |
|||
|
|||
self.ignorados = 0 |
|||
self.counter = 0 |
|||
|
|||
for r in self.dados: |
|||
self.counter += 1 |
|||
record = r.copy() |
|||
|
|||
if "interlegis.leg.br" in record["url"]: |
|||
self.ignorados += 1 |
|||
continue |
|||
|
|||
record["url"] = url_normalize(record["url"]) |
|||
|
|||
record["creationDate"] = ( |
|||
datetime.strptime(record["creationDate"], "%d/%m/%Y").date() |
|||
if "creationDate" in record and record["creationDate"] != "" |
|||
else None |
|||
) |
|||
record["suspendedDate"] = ( |
|||
datetime.strptime(record["suspendedDate"], "%d/%m/%Y").date() |
|||
if "suspendedDate" in record and record["suspendedDate"] != "" |
|||
else None |
|||
) |
|||
|
|||
yield record |
|||
|
|||
def get_tipo_servico(self, rec): |
|||
# Verificar se existe sub-serviço |
|||
if rec["namespace"].count("-") > 1: |
|||
subservico = rec["namespace"].split("-")[0] |
|||
try: |
|||
tipo_servico = TipoServico.objects.get(tipo_rancher=subservico) |
|||
return tipo_servico |
|||
except TipoServico.DoesNotExist: |
|||
# Tenta encontrar o serviço principal |
|||
pass |
|||
try: |
|||
tipo_servico = TipoServico.objects.get(tipo_rancher=rec["tipo"]) |
|||
except TipoServico.DoesNotExist: |
|||
print( |
|||
"* ", |
|||
_( |
|||
"Erro ao processar {counter}º registro. Tipo de " |
|||
"serviço desconhecido: {tipo}. Registro: {r}" |
|||
).format(counter=self.counter, tipo=rec["tipo"], r=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
return tipo_servico |
|||
|
|||
def get_orgao(self, rec): |
|||
# Tenta achar pelo namespace, que é mais canônico |
|||
|
|||
namespace = rec["namespace"] |
|||
if namespace.count("-") > 1: |
|||
namespace = "-".join(namespace.split("-")[1:]) |
|||
if namespace in self.nomes_gerados: |
|||
return self.nomes_gerados[namespace] |
|||
|
|||
# Senão, vamos buscar pelo tipo de órgão e nome |
|||
try: |
|||
tipo, nome_uf = rec["orgao"].split(" - ") |
|||
if nome_uf.count("-") > 1: |
|||
subproduto, nome, uf = nome_uf.split("-") |
|||
else: |
|||
nome, uf = nome_uf.split("-") |
|||
except ValueError: |
|||
print( |
|||
"* ", |
|||
_( |
|||
"Nome do órgão fora do padrão no {counter}º registro: {r}" |
|||
).format(counter=self.counter, r=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
tipo = to_ascii(tipo).lower() |
|||
nome = to_ascii(nome).lower() |
|||
uf = to_ascii(uf).lower() |
|||
cidade_uf = "-".join([nome, uf]) |
|||
|
|||
try: |
|||
tipo_orgao = TipoOrgao.objects.get(nome__unaccent__icontains=tipo) |
|||
except TipoOrgao.DoesNotExist: |
|||
print( |
|||
"* ", |
|||
_( |
|||
"Tipo de órgão desconhecido no {counter}º " |
|||
"registro. Nome do órgão: {orgao}, registro: {r}" |
|||
).format(counter=self.counter, orgao=rec["orgao"], r=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
|
|||
if cidade_uf in self.nomes_gerados: |
|||
orgao = self.nomes_gerados[cidade_uf] |
|||
if orgao.tipo != tipo_orgao: |
|||
print( |
|||
"* ", |
|||
_( |
|||
"Encontrado um órgão para o municipio " |
|||
"{municipio} - {uf}, mas o tipo de órgão difere do " |
|||
"recebido do webservice. Registro: {rec}" |
|||
).format(municipio=nome, uf=uf, rec=rec), |
|||
file=sys.stderr, |
|||
) |
|||
return False |
|||
return orgao |
|||
|
|||
return False |
|||
|
|||
def get_servico(self, tipo_servico, rec): |
|||
servicos = Servico.objects.filter( |
|||
tipo_servico=tipo_servico, |
|||
instancia=rec["namespace"], |
|||
data_desativacao=None, |
|||
).order_by("-data_ativacao") |
|||
# Nenhum serviço ativo nesse namespace. Podemos criar um novo |
|||
if not servicos: |
|||
return None |
|||
if len(servicos) == 1: |
|||
# Um único serviço ativo, deve ser esse |
|||
return servicos[0] |
|||
# Mais de um serviço ativo para este namespace. |
|||
# Não tem como decidir qual atualizar |
|||
raise MultipleServicesReturned( |
|||
_( |
|||
"Existem {qty} serviços ativos para o namespace {namespace}. " |
|||
"Registro {r}" |
|||
).format(qty=len(servicos), namespace=rec["namespace"], r=rec) |
|||
) |
|||
|
|||
def atualiza_servico(self, servico, rec): |
|||
log_tit = [] |
|||
log_txt = [] |
|||
|
|||
updated = False |
|||
|
|||
for attrname, recfield in self.UPDATABLE_FIELDS: |
|||
old = getattr(servico, attrname) |
|||
new = rec[recfield] |
|||
if old != new: |
|||
updated = True |
|||
log_tit.append( |
|||
_(f"Mudança de {attrname}").format( |
|||
attrname=attrname.upper() |
|||
) |
|||
) |
|||
log_txt.append( |
|||
_( |
|||
"A {attrname} do serviço foi alterada na " |
|||
"infraestrutura de {old} para {new}." |
|||
).format(attrname=attrname, old=old, new=new) |
|||
) |
|||
setattr(servico, attrname, new) |
|||
|
|||
if ( |
|||
rec["status"] == "suspenso" and servico.data_desativacao is None |
|||
) or ( |
|||
rec["suspendedDate"] is not None |
|||
and servico.data_desativacao != rec["suspendedDate"] |
|||
): |
|||
servico.data_desativacao = rec["suspendedDate"] |
|||
servico.motivo_desativacao = _( |
|||
"Serviço suspenso no SEIT e atualizado automaticamente " |
|||
"pelo processo de cron." |
|||
) |
|||
log_tit.append(_("Serviço suspenso no SEIT")) |
|||
log_txt.append( |
|||
_( |
|||
"Serviço suspenso no SEIT e atualizado automaticamente " |
|||
"pelo processo de cron." |
|||
) |
|||
) |
|||
print( |
|||
"* ", |
|||
_("{servico} de {orgao} desativado").format( |
|||
servico=servico.tipo_servico.nome, |
|||
orgao=servico.casa_legislativa.nome, |
|||
), |
|||
) |
|||
self.desativados += 1 |
|||
elif updated: |
|||
self.updates += 1 |
|||
print( |
|||
"* ", |
|||
_("{servico} de {orgao} atualizado").format( |
|||
servico=servico.tipo_servico.nome, |
|||
orgao=servico.casa_legislativa.nome, |
|||
), |
|||
) |
|||
|
|||
servico.flag_confirmado = True |
|||
servico.save() |
|||
if log_tit: |
|||
log_tit = ", ".join(log_tit) |
|||
log_txt = "\n\n".join(log_txt) |
|||
servico.logservico_set.create( |
|||
descricao=log_tit, |
|||
data=timezone.localdate(), |
|||
log=log_txt, |
|||
) |
|||
self.admin_log_change(servico, log_txt) |
|||
|
|||
def cria_servico(self, rec, tipo_servico, orgao): |
|||
servico = Servico( |
|||
casa_legislativa=orgao, |
|||
tipo_servico=tipo_servico, |
|||
url=rec["url"], |
|||
versao=rec["version"], |
|||
hospedagem_interlegis=True, |
|||
instancia=rec["namespace"], |
|||
data_ativacao=rec["creationDate"], |
|||
data_desativacao=rec["suspendedDate"], |
|||
motivo_desativacao=( |
|||
"" if rec["suspendedDate"] is None else _("Suspenso no SEIT") |
|||
), |
|||
flag_confirmado=True, |
|||
) |
|||
servico.save() |
|||
servico.logservico_set.create( |
|||
descricao=_("Serviço criado no SEIT"), |
|||
data=timezone.localdate(), |
|||
log=_( |
|||
"Servico criado no SEIT e atualizado no SIGI " |
|||
"automaticamente pelo processo de CRON" |
|||
), |
|||
) |
|||
self.admin_log_addition( |
|||
servico, |
|||
_( |
|||
"Servico criado no SEIT e atualizado no SIGI " |
|||
"automaticamente pelo processo de CRON" |
|||
), |
|||
) |
|||
print( |
|||
"* ", |
|||
_("{servico} criado para {orgao}").format( |
|||
servico=servico.tipo_servico.nome, |
|||
orgao=servico.casa_legislativa.nome, |
|||
), |
|||
) |
|||
|
|||
def bulk_desativa(self, servicos): |
|||
log_list = [ |
|||
LogServico( |
|||
servico=s, |
|||
descricao=_("Serviço desativado no SEIT"), |
|||
data=timezone.localdate(), |
|||
log=_( |
|||
"Desativado automaticamente pois não foi encontrado na " |
|||
"Infraestrutura do Interlegis" |
|||
), |
|||
) |
|||
for s in servicos |
|||
] |
|||
LogServico.objects.bulk_create(log_list) |
|||
self.admin_log_change( |
|||
servicos, |
|||
_( |
|||
"Desativado automaticamente pois não foi encontrado na " |
|||
"Infraestrutura do Interlegis" |
|||
), |
|||
) |
|||
print( |
|||
*[ |
|||
_( |
|||
"* {servico} de {orgao} desativado porque não consta nos " |
|||
"dados do webservice do SEIT\n" |
|||
).format( |
|||
servico=s.tipo_servico.nome, orgao=s.casa_legislativa.nome |
|||
) |
|||
for s in servicos |
|||
], |
|||
) |
|||
return servicos.update( |
|||
data_desativacao=timezone.localdate(), |
|||
motivo_desativacao=_( |
|||
"Desativado automaticamente pois não foi encontrado na " |
|||
"Infraestrutura do Interlegis" |
|||
), |
|||
) |
|||
@ -1,335 +0,0 @@ |
|||
import json |
|||
import shutil |
|||
import sys |
|||
from django.conf import settings |
|||
from django.db.models import Q |
|||
from django.template.loader import render_to_string |
|||
from django.utils import timezone |
|||
from django.utils.translation import gettext as _ |
|||
from django_extensions.management.jobs import DailyJob |
|||
from sigi.apps.servicos import generate_instance_name, nomeia_instancias |
|||
from sigi.apps.servicos.models import Servico, TipoServico |
|||
from sigi.apps.casas.models import Orgao |
|||
from sigi.apps.contatos.models import UnidadeFederativa |
|||
from sigi.apps.utils.management.jobs import AdminJobMixin |
|||
|
|||
LOG_GERAL = _("Mensagens gerais") |
|||
IGNORES = ["_psl", "k8s", "www.", "sapl.", "addr.arpa"] |
|||
|
|||
get_iname = lambda d: "-".join(d.split(".")[:-2]) |
|||
get_sigla_serv = lambda d: "".join(d.split(".")[-2:]).upper() |
|||
get_sigla_uf = lambda d: "".join(d.split(".")[-3:-2]).upper() |
|||
|
|||
|
|||
def get_log_entry(): |
|||
return { |
|||
"sumario": { |
|||
"total": 0, |
|||
"novos": 0, |
|||
"atualizados": 0, |
|||
"desativados": 0, |
|||
"ignorados": 0, |
|||
}, |
|||
"infos": [], |
|||
"erros": [], |
|||
} |
|||
|
|||
|
|||
class Job(AdminJobMixin, DailyJob): |
|||
help = _("Sincronização dos registros de DNS da infraestrutura") |
|||
nomes_gerados = None |
|||
report_data = {} |
|||
|
|||
def execute(self): |
|||
self.report_data[LOG_GERAL] = get_log_entry() |
|||
|
|||
if ( |
|||
not settings.REGISTRO_PATH.exists() |
|||
or not settings.REGISTRO_PATH.is_dir() |
|||
): |
|||
self.error(_(f"Arquivos de DNS não encontrados.")) |
|||
return |
|||
|
|||
self.nomes_gerados = { |
|||
generate_instance_name(o): o |
|||
for o in Orgao.objects.filter(tipo__legislativo=True) |
|||
} |
|||
|
|||
Servico.objects.filter( |
|||
tipo_servico__modo="R", data_desativacao=None |
|||
).update(flag_confirmado=False) |
|||
|
|||
nomeia_instancias( |
|||
servicos=Servico.objects.filter( |
|||
tipo_servico__modo="R", data_desativacao=None, instancia="" |
|||
), |
|||
user=self.sys_user, |
|||
) |
|||
|
|||
# Remove arquivo ZONES, desnecessário para este processo # |
|||
zones_file = settings.REGISTRO_PATH / "ZONES" |
|||
if zones_file.exists() and zones_file.is_file(): |
|||
zones_file.unlink() |
|||
|
|||
for uf in UnidadeFederativa.objects.all(): |
|||
self.report_data[uf] = get_log_entry() |
|||
self.processa_uf(uf) |
|||
|
|||
# self.processa_zones() |
|||
self.processa_files() |
|||
|
|||
try: |
|||
shutil.rmtree(settings.REGISTRO_PATH) |
|||
except Exception as e: |
|||
self.error(_(f"Erro ao excluir diretório {settings.REGISTRO_PATH}")) |
|||
print( |
|||
render_to_string( |
|||
"servicos/emails/report_sincroniza_dns.rst", |
|||
context={"report_data": self.report_data}, |
|||
) |
|||
) |
|||
if any([len(d.erros) > 0 for uf, d in self.report_data.items()]): |
|||
print("* EXISTEM ERROS A SEREM ANALISADOS *", file=sys.stderr) |
|||
|
|||
def processa_rec(self, dns_rec, log_entry=LOG_GERAL): |
|||
dominio = dns_rec["name"][:-1] |
|||
nivel = dominio.count(".") + 1 |
|||
iname = get_iname(dominio) |
|||
sigla_srv = get_sigla_serv(dominio) |
|||
|
|||
if any([i in dominio for i in IGNORES]): |
|||
# Ignorar esses registros sem fazer log # |
|||
return |
|||
|
|||
try: |
|||
tipo = TipoServico.objects.get(sigla=sigla_srv, modo="R") |
|||
except TipoServico.DoesNotExist: |
|||
self.log_ignore( |
|||
dominio, |
|||
_("não coincide com nenhum tipo de serviço de registro SEIT"), |
|||
log_entry, |
|||
) |
|||
return |
|||
|
|||
if log_entry == LOG_GERAL: |
|||
try: |
|||
log_entry = UnidadeFederativa.objects.get( |
|||
sigla=get_sigla_uf(dominio) |
|||
) |
|||
except: |
|||
pass |
|||
|
|||
detail_file = settings.REGISTRO_PATH / f"{dominio}." |
|||
hospedado_interlegis = detail_file.exists() and detail_file.is_file() |
|||
|
|||
filtro_base = Q(instancia=iname) | Q(url=dominio) |
|||
if iname in self.nomes_gerados: |
|||
filtro_base = filtro_base | Q( |
|||
casa_legislativa=self.nomes_gerados[iname] |
|||
) |
|||
filtro_base = filtro_base & Q(tipo_servico=tipo) |
|||
|
|||
servico = None |
|||
novo = False |
|||
|
|||
try: |
|||
servico = Servico.objects.get( |
|||
filtro_base & Q(data_desativacao=None) |
|||
) |
|||
except Servico.MultipleObjectsReturned: |
|||
self.log_ignore( |
|||
dominio, |
|||
_( |
|||
"existe mais de um registro no SIGI para a instância " |
|||
f"{iname}, domínio {dominio}" |
|||
), |
|||
log_entry, |
|||
) |
|||
return |
|||
except Servico.DoesNotExist: |
|||
# Tenta encontrar um registro desativado para esta instância # |
|||
servico = Servico.objects.filter( |
|||
filtro_base & ~Q(data_desativacao=None) |
|||
).first() |
|||
if servico is not None: |
|||
# Reativa o servico # |
|||
self.log_reativa(servico) |
|||
servico.data_desativacao = None |
|||
servico.motivo_desativacao = "" |
|||
servico.instancia = iname |
|||
self.admin_log_change(servico, _("Reativado pelo DNS Rancher")) |
|||
else: |
|||
# Tenta criar o registro # |
|||
if iname in self.nomes_gerados: |
|||
orgao = self.nomes_gerados[iname] |
|||
log_entry = orgao.municipio.uf |
|||
servico = Servico( |
|||
casa_legislativa=orgao, |
|||
tipo_servico=tipo, |
|||
url=dominio, |
|||
instancia=iname, |
|||
hospedagem_interlegis=hospedado_interlegis, |
|||
data_ativacao=timezone.localdate(), |
|||
flag_confirmado=True, |
|||
resultado_verificacao="N", # Não verificado |
|||
) |
|||
servico.save() |
|||
novo = True |
|||
self.log_novo(servico) |
|||
self.admin_log_addition(servico, "Criado pelo DNS Rancher") |
|||
|
|||
if servico is None: |
|||
if nivel > 3: |
|||
# Loga registro não encontrado apenas para 4º+ nível # |
|||
self.log_ignore( |
|||
dominio, |
|||
_("não parece pertencer a nenhum órgão"), |
|||
log_entry, |
|||
) |
|||
elif not novo: |
|||
# atualiza o serviço no SIGI |
|||
updates = [] |
|||
if servico.url != dominio: |
|||
updates.append(_(f"Url de '{servico.url}' para '{dominio}'")) |
|||
if servico.instancia != iname: |
|||
updates.append( |
|||
_(f"Instância de '{servico.instancia}' para '{iname}'") |
|||
) |
|||
if servico.hospedagem_interlegis != hospedado_interlegis: |
|||
updates.append( |
|||
"Veio para hospedagem no Interlegis" |
|||
if hospedado_interlegis |
|||
else "Passou a ser delegado" |
|||
) |
|||
servico.url = dominio |
|||
servico.instancia = iname |
|||
servico.hospedagem_interlegis = hospedado_interlegis |
|||
servico.flag_confirmado = True |
|||
servico.save() |
|||
if updates: |
|||
self.log_update(servico) |
|||
self.admin_log_change( |
|||
servico, |
|||
"Atualizado pelo DNS Rancher: " + ", ".join(updates), |
|||
) |
|||
|
|||
def processa_uf(self, uf): |
|||
file_path = settings.REGISTRO_PATH / f"{uf.sigla.lower()}.leg.br." |
|||
if not file_path.exists() or not file_path.is_file(): |
|||
self.error(_(f"Arquivo {file_path} não encontado."), uf) |
|||
return |
|||
|
|||
registros = json.loads(file_path.read_text())["rrsets"] |
|||
self.report_data[uf]["sumario"]["total"] = len(registros) |
|||
|
|||
# Atualiza registros existentes e cria novos # |
|||
for rec in registros: |
|||
dominio = rec["name"][:-1] |
|||
self.processa_rec(rec, uf) |
|||
# Remove arquivo de detalhe, se existente # |
|||
detail_file = settings.REGISTRO_PATH / f"{dominio}." |
|||
if ( |
|||
detail_file != file_path |
|||
and detail_file.exists() |
|||
and detail_file.is_file() |
|||
): |
|||
detail_file.unlink() |
|||
|
|||
# Remove arquivo da UF # |
|||
file_path.unlink() |
|||
|
|||
# def processa_zones(self): |
|||
# zones_file = settings.REGISTRO_PATH / "ZONES" |
|||
# if not zones_file.exists() or not zones_file.is_file(): |
|||
# self.error( |
|||
# _( |
|||
# f"Arquivo de zonas {zones_file} não encontrado ou " |
|||
# "não é arquivo" |
|||
# ) |
|||
# ) |
|||
# return |
|||
# data = json.loads(zones_file.read_text()) |
|||
# for rec in data: |
|||
# dominio = rec["name"][:-1] |
|||
# self.processa_rec(rec) |
|||
# detail_file = settings.REGISTRO_PATH / f"{dominio}." |
|||
# if ( |
|||
# detail_file != zones_file |
|||
# and detail_file.exists() |
|||
# and detail_file.is_file() |
|||
# ): |
|||
# detail_file.unlink() |
|||
|
|||
# zones_file.unlink() |
|||
|
|||
def processa_files(self): |
|||
file_list = list(settings.REGISTRO_PATH.iterdir()) |
|||
self.report_data[LOG_GERAL]["sumario"]["total"] = len(file_list) |
|||
for file_path in file_list: |
|||
if not file_path.is_file(): |
|||
self.report_data[LOG_GERAL]["sumario"]["total"] -= 1 |
|||
continue |
|||
data = json.loads(file_path.read_text()) |
|||
self.processa_rec(data) |
|||
file_path.unlink() |
|||
|
|||
def remove_sigi(self): |
|||
# Desativa registros no SIGI que não estão no DNS # |
|||
for servico in Servico.objects.filter( |
|||
tipo_servico__modo="R", |
|||
data_desativacao=None, |
|||
flag_confirmado=False, |
|||
): |
|||
servico.data_desativacao = timezone.localdate() |
|||
servico.motivo_desativacao = _("Não encontrado no DNS") |
|||
servico.save() |
|||
self.log_remove(servico) |
|||
self.admin_log_change( |
|||
servico, _("Desativado: não encontrado no DNS Rancher") |
|||
) |
|||
|
|||
def error(self, message, log_entry=LOG_GERAL): |
|||
self.report_data[log_entry]["erros"].append(message) |
|||
|
|||
def info(self, message, log_entry=LOG_GERAL): |
|||
self.report_data[log_entry]["infos"].append(message) |
|||
|
|||
def log_novo(self, srv): |
|||
orgao = srv.casa_legislativa |
|||
uf = orgao.municipio.uf |
|||
msg = _( |
|||
f"Criada instância {srv.instancia} de {srv.tipo_servico.nome} " |
|||
f"para {orgao.nome} ({uf.sigla})" |
|||
) |
|||
self.info(msg, uf) |
|||
self.report_data[uf]["sumario"]["novos"] += 1 |
|||
|
|||
def log_ignore(self, dominio, motivo, log_entry=LOG_GERAL): |
|||
self.error(_(f"Registro {dominio} ignorado pois {motivo}"), log_entry) |
|||
self.report_data[log_entry]["sumario"]["ignorados"] += 1 |
|||
|
|||
def log_update(self, srv): |
|||
uf = srv.casa_legislativa.municipio.uf |
|||
self.report_data[uf]["sumario"]["atualizados"] += 1 |
|||
|
|||
def log_reativa(self, srv): |
|||
orgao = srv.casa_legislativa |
|||
uf = orgao.municipio.uf |
|||
msg = _( |
|||
f"Instância {srv.instancia} de {srv.tipo_servico.nome} " |
|||
f"para {orgao.nome} ({uf.sigla}) reativada no SIGI" |
|||
) |
|||
self.report_data[uf]["sumario"]["atualizados"] += 1 |
|||
self.info(msg, uf) |
|||
|
|||
def log_remove(self, srv): |
|||
orgao = srv.casa_legislativa |
|||
uf = orgao.municipio.uf |
|||
self.report_data[uf]["sumario"]["desativados"] += 1 |
|||
self.info( |
|||
_( |
|||
f"Registro {srv.tipo_servico.sigla} {srv.instancia} ({srv.url})" |
|||
f" de {orgao.nome} desativado pois não foi encontrado no DNS." |
|||
), |
|||
uf, |
|||
) |
|||
@ -1,248 +0,0 @@ |
|||
import json |
|||
import shutil |
|||
import sys |
|||
from django.conf import settings |
|||
from django.utils import timezone |
|||
from django.utils.translation import gettext as _ |
|||
from django_extensions.management.jobs import DailyJob |
|||
from sigi.apps.servicos import generate_instance_name, nomeia_instancias |
|||
from sigi.apps.servicos.models import Servico, TipoServico |
|||
from sigi.apps.casas.models import Orgao |
|||
from sigi.apps.utils.management.jobs import AdminJobMixin |
|||
|
|||
|
|||
class Job(AdminJobMixin, DailyJob): |
|||
help = _("Sincronização dos Serviços SEIT na infraestrutura") |
|||
report_template = "servicos/emails/report_sincroniza_rancher.rst" |
|||
nomes_gerados = None |
|||
|
|||
def execute(self): |
|||
self.nomes_gerados = { |
|||
generate_instance_name(o): o |
|||
for o in Orgao.objects.filter(tipo__legislativo=True) |
|||
} |
|||
|
|||
for tipo in TipoServico.objects.filter(modo="H").exclude( |
|||
tipo_rancher="" |
|||
): |
|||
self.process(tipo) |
|||
|
|||
try: |
|||
shutil.rmtree(settings.HOSPEDAGEM_PATH) |
|||
except Exception as e: |
|||
pass |
|||
|
|||
def process(self, tipo): |
|||
nomeia_instancias( |
|||
servicos=Servico.objects.filter( |
|||
tipo_servico=tipo, data_desativacao=None, instancia="" |
|||
), |
|||
user=self.sys_user, |
|||
) |
|||
NAO_CONSTA = "*não-consta-no-rancher*" |
|||
|
|||
file_path = settings.HOSPEDAGEM_PATH / tipo.arquivo_rancher |
|||
if not file_path.exists() or not file_path.is_file(): |
|||
print( |
|||
f"{tipo}: Arquivo {file_path} não encontado.", file=sys.stderr |
|||
) |
|||
return |
|||
|
|||
json_data = json.loads(file_path.read_text()) |
|||
|
|||
portais = [ |
|||
item |
|||
for item in json_data["items"] |
|||
if item["kind"].lower() == "app" |
|||
and item["spec"]["chart"]["metadata"]["name"] == tipo.tipo_rancher |
|||
] |
|||
namespaces = [ |
|||
item |
|||
for item in json_data["items"] |
|||
if item["kind"].lower() == "namespace" |
|||
] |
|||
|
|||
encontrados = 0 |
|||
novos = 0 |
|||
desativados = 0 |
|||
|
|||
print(f"{len(portais)} {tipo.nome} encontrados no Rancher") |
|||
|
|||
# Atualiza portais existentes e cria novos # |
|||
for p in portais: |
|||
namespace = p["metadata"]["namespace"] |
|||
name = p["metadata"]["name"] |
|||
if tipo.spec_rancher in p["spec"]["values"]: |
|||
if "hostname" in p["spec"]["values"][tipo.spec_rancher]: |
|||
hostname = p["spec"]["values"][tipo.spec_rancher][ |
|||
"hostname" |
|||
] |
|||
elif "domain" in p["spec"]["values"][tipo.spec_rancher]: |
|||
hostname = p["spec"]["values"][tipo.spec_rancher]["domain"] |
|||
else: |
|||
hostname = NAO_CONSTA |
|||
print( |
|||
f"Instância {namespace} de {tipo.nome} sem URL no " |
|||
"rancher", |
|||
file=sys.stderr, |
|||
) |
|||
|
|||
if "hostprefix" in p["spec"]["values"][tipo.spec_rancher]: |
|||
prefix = p["spec"]["values"][tipo.spec_rancher][ |
|||
"hostprefix" |
|||
] |
|||
hostname = f"{prefix}.{hostname}" |
|||
elif tipo.prefixo_padrao != "": |
|||
hostname = f"{tipo.prefixo_padrao}.{hostname}" |
|||
else: |
|||
hostname = NAO_CONSTA |
|||
print( |
|||
f"Instância {namespace} de {tipo.nome} sem URL no rancher", |
|||
file=sys.stderr, |
|||
) |
|||
|
|||
nova_versao = ( |
|||
p["spec"]["values"]["image"]["tag"] |
|||
if "image" in p["spec"]["values"] |
|||
else "" |
|||
) |
|||
if NAO_CONSTA in hostname: |
|||
nova_url = "" |
|||
else: |
|||
nova_url = f"https://{hostname}/" |
|||
|
|||
# Identificar registro de suspensão do namespace |
|||
suspenso = [ |
|||
ns["metadata"]["annotations"]["suspenso"] |
|||
for ns in namespaces |
|||
if ns["metadata"]["name"] == namespace |
|||
and "suspenso" in ns["metadata"]["annotations"] |
|||
] |
|||
|
|||
try: |
|||
portal = Servico.objects.get( |
|||
instancia=namespace, |
|||
tipo_servico=tipo, |
|||
data_desativacao=None, |
|||
) |
|||
encontrados += 1 |
|||
except Servico.MultipleObjectsReturned: |
|||
print( |
|||
f"Existe mais de um registro ativo da instância " |
|||
f"{namespace} de {tipo}.", |
|||
file=sys.stderr, |
|||
) |
|||
continue |
|||
except Servico.DoesNotExist: |
|||
# Se a instância está suspensa, não precisa criar o registro |
|||
# no SIGI. |
|||
if suspenso: |
|||
continue |
|||
if ( |
|||
namespace in self.nomes_gerados |
|||
or name in self.nomes_gerados |
|||
): |
|||
orgao = ( |
|||
self.nomes_gerados[namespace] |
|||
if namespace in self.nomes_gerados |
|||
else self.nomes_gerados[name] |
|||
) |
|||
portal = Servico( |
|||
casa_legislativa=orgao, |
|||
tipo_servico=tipo, |
|||
instancia=namespace, |
|||
url=nova_url, |
|||
versao=nova_versao, |
|||
data_ativacao=p["spec"]["info"]["firstDeployed"][:10], |
|||
hospedagem_interlegis=True, |
|||
) |
|||
portal.save() |
|||
self.admin_log_addition(portal, "Criado no Rancher") |
|||
novos += 1 |
|||
print( |
|||
f"Criada instância {namespace} de {tipo.nome} para " |
|||
f"{orgao.nome} ({orgao.municipio.uf.sigla})" |
|||
) |
|||
else: |
|||
print( |
|||
f"{namespace} ({hostname}) não parece pertencer a " |
|||
"nenhum órgão.", |
|||
file=sys.stderr, |
|||
) |
|||
continue |
|||
# se tem registro de suspensão do namespace |
|||
if suspenso: |
|||
# Desativar o portal no SIGI |
|||
apontamentos = ", ".join([f'"{s}"' for s in suspenso]) |
|||
portal.data_desativacao = timezone.localdate() |
|||
portal.motivo_desativacao = ( |
|||
"Suspenso no Rancher com os seguintes apontamentos:" |
|||
+ apontamentos |
|||
) |
|||
portal.save() |
|||
self.admin_log_change(portal, portal.motivo_desativacao) |
|||
print( |
|||
f"{portal.tipo_servico} em {portal.url} de " |
|||
f"{portal.casa_legislativa} suspenso no Rancher com os" |
|||
f"seguintes apontamentos: {apontamentos}" |
|||
) |
|||
# atualiza o serviço no SIGI |
|||
if ( |
|||
nova_versao != portal.versao |
|||
or nova_url != portal.url |
|||
or not portal.hospedagem_interlegis |
|||
): |
|||
message = ( |
|||
"Atualizado no Rancher: " |
|||
+ ( |
|||
f"Versão: de '{portal.versao}' para '{nova_versao}' " |
|||
if portal.versao != nova_versao |
|||
else "" |
|||
) |
|||
+ ( |
|||
f"Url: de '{portal.url}' para '{nova_url}' " |
|||
if portal.url != nova_url |
|||
else "" |
|||
) |
|||
+ ( |
|||
"hospedagem interlegis" |
|||
if not portal.hospedagem_interlegis |
|||
else "" |
|||
) |
|||
) |
|||
portal.versao = nova_versao |
|||
portal.url = nova_url |
|||
portal.hospedagem_interlegis = True |
|||
portal.save() |
|||
self.admin_log_change(portal, message) |
|||
print( |
|||
f"{portal.tipo_servico} em {portal.url} de " |
|||
f"{portal.casa_legislativa} atualizado no Rancher: " |
|||
+ message |
|||
) |
|||
|
|||
# Desativa portais registrados no SIGI que não estão no Rancher # |
|||
nomes_instancias = [p["metadata"]["name"] for p in portais] |
|||
for portal in Servico.objects.filter( |
|||
tipo_servico=tipo, |
|||
data_desativacao=None, |
|||
hospedagem_interlegis=True, |
|||
): |
|||
if ( |
|||
portal.instancia == "" |
|||
or portal.instancia not in nomes_instancias |
|||
): |
|||
portal.data_desativacao = timezone.localdate() |
|||
portal.motivo_desativacao = _("Não encontrado no Rancher") |
|||
portal.save() |
|||
self.admin_log_change(portal, "Desativado no Rancher") |
|||
print( |
|||
f"{portal.instancia} ({portal.url}) de " |
|||
f"{portal.casa_legislativa.nome} desativado pois não " |
|||
"foi encontrado no Rancher." |
|||
) |
|||
desativados += 1 |
|||
|
|||
print(f"{encontrados} {tipo.nome} do Rancher encontrados no SIGI") |
|||
print(f"{novos} novos {tipo.nome} criados no SIGI") |
|||
print(f"{desativados} {tipo.nome} desativados no SIGI") |
|||
@ -0,0 +1,21 @@ |
|||
# Generated by Django 6.0.4 on 2026-08-07 15:17 |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
("servicos", "0022_atualiza_mail_leg"), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RemoveField( |
|||
model_name="tiposervico", |
|||
name="arquivo_rancher", |
|||
), |
|||
migrations.RemoveField( |
|||
model_name="tiposervico", |
|||
name="spec_rancher", |
|||
), |
|||
] |
|||
@ -0,0 +1,23 @@ |
|||
# Generated by Django 6.0.4 on 2026-08-07 15:18 |
|||
from url_normalize import url_normalize |
|||
from django.contrib.postgres.operations import UnaccentExtension |
|||
from django.db import migrations |
|||
|
|||
|
|||
def mormaliza_urls(apps, schema_editor): |
|||
Servico = apps.get_model("servicos", "Servico") |
|||
for s in Servico.objects.filter(tipo_servico__modo="H").exclude(url=""): |
|||
s.url = url_normalize(s.url) |
|||
s.save() |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
("servicos", "0023_remove_tiposervico_arquivo_rancher_and_more"), |
|||
] |
|||
|
|||
operations = [ |
|||
UnaccentExtension(), |
|||
migrations.RunPython(mormaliza_urls, migrations.RunPython.noop), |
|||
] |
|||
@ -0,0 +1,32 @@ |
|||
# Generated by Django 6.0.4 on 2026-08-12 14:30 |
|||
|
|||
from django.db import migrations |
|||
|
|||
SIGLA_X_RANCHER = ( |
|||
("GOVBR", "GOV.BR"), |
|||
("LEGBR", "LEG.BR"), |
|||
("DNSREV", "DNS reverso"), |
|||
) |
|||
|
|||
|
|||
def update_registros(apps, schema_editor): |
|||
TipoServico = apps.get_model("servicos", "TipoServico") |
|||
for sigla, tipo_rancher in SIGLA_X_RANCHER: |
|||
TipoServico.objects.filter(sigla=sigla).update( |
|||
tipo_rancher=tipo_rancher |
|||
) |
|||
|
|||
|
|||
def reverse_registros(apps, schema_editor): |
|||
TipoServico = apps.get_model("servicos", "TipoServico") |
|||
for sigla, tipo_rancher in SIGLA_X_RANCHER: |
|||
TipoServico.objects.filter(sigla=sigla).update(tipo_rancher="") |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
("servicos", "0024_auto_20260807_1218"), |
|||
] |
|||
|
|||
operations = [migrations.RunPython(update_registros, reverse_registros)] |
|||
Loading…
Reference in new issue