mirror of https://github.com/interlegis/sigi.git
Sesostris Vieira
2 years ago
8 changed files with 357 additions and 0 deletions
@ -0,0 +1,19 @@ |
|||||
|
def generate_instance_name(orgao): |
||||
|
import re |
||||
|
from sigi.apps.utils import to_ascii |
||||
|
|
||||
|
# Orgao deve ser uma instância de sigi.apps.casas.models.Orgao # |
||||
|
if orgao.tipo.sigla == "CM": |
||||
|
return ( |
||||
|
re.sub("\W+", "", to_ascii(orgao.municipio.nome)).lower() |
||||
|
+ "-" |
||||
|
+ orgao.municipio.uf.sigla.lower() |
||||
|
) |
||||
|
elif orgao.tipo.sigla == "CT": |
||||
|
return "cl-df" |
||||
|
elif orgao.tipo.sigla == "AL": |
||||
|
return f"al-{orgao.municipio.uf.sigla.lower()}" |
||||
|
elif orgao.tipo.sigla in ["CD", "SF"]: |
||||
|
return re.sub("\W+", "", to_ascii(orgao.nome)).lower() |
||||
|
else: |
||||
|
return f"{orgao.tipo.sigla.lower()}-{orgao.municipio.uf.sigla.lower()}" |
@ -0,0 +1,204 @@ |
|||||
|
import datetime |
||||
|
import docutils.core |
||||
|
import json |
||||
|
from pathlib import Path |
||||
|
from django.conf import settings |
||||
|
from django.core.mail import mail_admins |
||||
|
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 |
||||
|
from sigi.apps.servicos.models import Servico, TipoServico |
||||
|
from sigi.apps.casas.models import Orgao |
||||
|
|
||||
|
|
||||
|
class Job(DailyJob): |
||||
|
help = _("Sincronização dos Serviços SEIT na infraestrutura") |
||||
|
_nomes_gerados = None |
||||
|
_errors = {} |
||||
|
_infos = {} |
||||
|
|
||||
|
def execute(self): |
||||
|
print( |
||||
|
_( |
||||
|
"Sincroniza os serviços SEIT a partir da infraestrutura." |
||||
|
f" Início: {datetime.datetime.now(): %d/%m/%Y %H:%M:%S}" |
||||
|
) |
||||
|
) |
||||
|
self._nomes_gerados = { |
||||
|
generate_instance_name(o): o |
||||
|
for o in Orgao.objects.filter(tipo__legislativo=True) |
||||
|
} |
||||
|
print(f"\t{len(self._nomes_gerados)} órgãos que podem ter instâncias.") |
||||
|
|
||||
|
for tipo in TipoServico.objects.filter(modo="H").exclude( |
||||
|
tipo_rancher="" |
||||
|
): |
||||
|
print( |
||||
|
_( |
||||
|
f"\tProcessando {tipo.nome}." |
||||
|
f" Início: {datetime.datetime.now():%H:%M:%S}." |
||||
|
), |
||||
|
end="", |
||||
|
) |
||||
|
self.process(tipo) |
||||
|
print(f" Término: {datetime.datetime.now():%H:%M:%S}.") |
||||
|
|
||||
|
print("Relatório final:\n================") |
||||
|
self.report() |
||||
|
|
||||
|
print(_(f"Término: {datetime.datetime.now(): %d/%m/%Y %H:%M:%S}")) |
||||
|
|
||||
|
def process(self, tipo): |
||||
|
NAO_CONSTA = "*não-consta-no-rancher*" |
||||
|
self._errors[tipo] = [] |
||||
|
self._infos[tipo] = [] |
||||
|
|
||||
|
file_path = settings.HOSPEDAGEM_PATH / tipo.arquivo_rancher |
||||
|
if not file_path.exists() or not file_path.is_file(): |
||||
|
self._errors[tipo].append(_(f"Arquivo {file_path} não encontado.")) |
||||
|
return |
||||
|
|
||||
|
with open(file_path, "r") as f: |
||||
|
json_data = json.load(f) |
||||
|
|
||||
|
portais = [ |
||||
|
item |
||||
|
for item in json_data["items"] |
||||
|
if item["spec"]["chart"]["metadata"]["name"] == tipo.tipo_rancher |
||||
|
] |
||||
|
|
||||
|
encontrados = 0 |
||||
|
novos = 0 |
||||
|
desativados = 0 |
||||
|
|
||||
|
self._infos[tipo].append( |
||||
|
_(f"{len(portais)} {tipo.nome} encontrados no Rancher") |
||||
|
) |
||||
|
|
||||
|
# Atualiza portais existentes e cria novos # |
||||
|
for p in portais: |
||||
|
iname = 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 |
||||
|
self._errors[tipo].append( |
||||
|
_( |
||||
|
f"Instância {iname} de {tipo.nome} sem URL no " |
||||
|
"rancher" |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
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 |
||||
|
self._errors[tipo].append( |
||||
|
_(f"Instância {iname} de {tipo.nome} sem URL no rancher") |
||||
|
) |
||||
|
|
||||
|
try: |
||||
|
portal = Servico.objects.get(instancia=iname, tipo_servico=tipo) |
||||
|
encontrados += 1 |
||||
|
except Servico.DoesNotExist: |
||||
|
if iname in self._nomes_gerados: |
||||
|
orgao = self._nomes_gerados[iname] |
||||
|
portal = Servico( |
||||
|
casa_legislativa=orgao, |
||||
|
tipo_servico=tipo, |
||||
|
instancia=iname, |
||||
|
data_ativacao=p["spec"]["info"]["firstDeployed"][:10], |
||||
|
) |
||||
|
self._infos[tipo].append( |
||||
|
_( |
||||
|
f"Criada instância {iname} de {tipo.nome} para " |
||||
|
f"{orgao.nome} ({orgao.municipio.uf.sigla})" |
||||
|
) |
||||
|
) |
||||
|
novos += 1 |
||||
|
else: |
||||
|
self._errors[tipo].append( |
||||
|
_( |
||||
|
f"{iname} ({hostname}) não parece pertencer a " |
||||
|
"nenhum órgão." |
||||
|
) |
||||
|
) |
||||
|
continue |
||||
|
# atualiza o serviço no SIGI |
||||
|
portal.versao = ( |
||||
|
p["spec"]["values"]["image"]["tag"] |
||||
|
if "image" in p["spec"]["values"] |
||||
|
else "" |
||||
|
) |
||||
|
if NAO_CONSTA in hostname: |
||||
|
portal.url = "" |
||||
|
else: |
||||
|
portal.url = f"https://{hostname}/" |
||||
|
portal.hospedagem_interlegis = True |
||||
|
portal.save() |
||||
|
|
||||
|
# 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._infos[tipo].append( |
||||
|
f"{portal.instancia} ({portal.url}) de " |
||||
|
f"{portal.casa_legislativa.nome} desativado pois não " |
||||
|
"foi encontrado no Rancher." |
||||
|
) |
||||
|
desativados += 1 |
||||
|
|
||||
|
self._infos[tipo].append( |
||||
|
_(f"{encontrados} {tipo.nome} do Rancher encontrados no SIGI") |
||||
|
) |
||||
|
self._infos[tipo].append( |
||||
|
_(f"{novos} novos {tipo.nome} criados no SIGI") |
||||
|
) |
||||
|
self._infos[tipo].append( |
||||
|
_(f"{desativados} {tipo.nome} desativados no SIGI") |
||||
|
) |
||||
|
|
||||
|
def report(self): |
||||
|
rst = render_to_string( |
||||
|
"servicos/emails/report_sincroniza_rancher.rst", |
||||
|
{ |
||||
|
"erros": self._errors, |
||||
|
"infos": self._infos, |
||||
|
"title": _("Resultado da sincronização do SIGI com o Rancher"), |
||||
|
}, |
||||
|
) |
||||
|
html = docutils.core.publish_string( |
||||
|
rst, |
||||
|
writer_name="html5", |
||||
|
settings_overrides={ |
||||
|
"input_encoding": "unicode", |
||||
|
"output_encoding": "unicode", |
||||
|
}, |
||||
|
) |
||||
|
mail_admins( |
||||
|
subject=self.help, |
||||
|
message=rst, |
||||
|
html_message=html, |
||||
|
fail_silently=True, |
||||
|
) |
||||
|
print(rst) |
@ -0,0 +1,53 @@ |
|||||
|
# Generated by Django 4.1.2 on 2022-10-20 15:13 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
("servicos", "0013_alter_logservico_data_alter_servico_data_ativacao"), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name="servico", |
||||
|
name="instancia", |
||||
|
field=models.CharField( |
||||
|
blank=True, max_length=100, verbose_name="nome da instância" |
||||
|
), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name="servico", |
||||
|
name="versao", |
||||
|
field=models.CharField(blank=True, max_length=20, verbose_name="versão"), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name="tiposervico", |
||||
|
name="arquivo_rancher", |
||||
|
field=models.CharField( |
||||
|
blank=True, |
||||
|
max_length=100, |
||||
|
verbose_name="nome do arquivo gerado no rancher", |
||||
|
), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name="tiposervico", |
||||
|
name="prefixo_padrao", |
||||
|
field=models.CharField(blank=True, max_length=20), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name="tiposervico", |
||||
|
name="spec_rancher", |
||||
|
field=models.CharField( |
||||
|
blank=True, max_length=100, verbose_name="spec do serviço no Rancher" |
||||
|
), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name="tiposervico", |
||||
|
name="tipo_rancher", |
||||
|
field=models.CharField( |
||||
|
blank=True, max_length=100, verbose_name="tipo de objeto no Rancher" |
||||
|
), |
||||
|
), |
||||
|
] |
@ -0,0 +1,27 @@ |
|||||
|
# Generated by Django 4.1.1 on 2022-10-03 21:00 |
||||
|
|
||||
|
from django.db import migrations |
||||
|
from sigi.apps.servicos import generate_instance_name |
||||
|
|
||||
|
|
||||
|
def instance_names_fw(apps, schema_editor): |
||||
|
Servico = apps.get_model("servicos", "Servico") |
||||
|
for s in Servico.objects.filter(data_desativacao=None): |
||||
|
s.instancia = generate_instance_name(s.casa_legislativa) |
||||
|
s.save() |
||||
|
|
||||
|
|
||||
|
def instance_names_rw(apps, schema_editor): |
||||
|
Servico = apps.get_model("servicos", "Servico") |
||||
|
Servico.objects.all().update(instancia="") |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
("servicos", "0014_servico_instancia_servico_versao_and_more"), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RunPython(instance_names_fw, instance_names_rw), |
||||
|
] |
@ -0,0 +1,34 @@ |
|||||
|
{% extends 'emails/base_email.rst' %} |
||||
|
{% load i18n %} |
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
{% trans "Resultado da sincronização dos dados de serviços do SIGI com as instâncias instaladas no Rancher." %} |
||||
|
|
||||
|
* {% trans "Data/hora de execução" %}: {% now 'SHORT_DATETIME_FORMAT' %} |
||||
|
|
||||
|
|
||||
|
**{% trans "ERROS ENCONTRADOS" %}** |
||||
|
===================== |
||||
|
{% for tipo, mensagens in erros.items %} |
||||
|
**{{ tipo.nome|upper }} - {{ tipo.sigla|upper }}** |
||||
|
{% for m in mensagens %} |
||||
|
* {{ m }} |
||||
|
{% endfor %} |
||||
|
{% empty %} |
||||
|
*{% trans "Nenhum erro encontrado" %}* |
||||
|
{% endfor %} |
||||
|
|
||||
|
|
||||
|
**{% trans "INFORMAÇÕES ADICIONAIS" %}** |
||||
|
========================== |
||||
|
{% for tipo, mensagens in infos.items %} |
||||
|
{{ tipo.nome|upper }} - {{ tipo.sigla|upper }} |
||||
|
{% for m in mensagens %} |
||||
|
* {{ m }} |
||||
|
{% endfor %} |
||||
|
{% empty %} |
||||
|
*{% trans "Nenhuma informação adicional gerada" %}* |
||||
|
{% endfor %} |
||||
|
|
||||
|
{% endblock content %} |
Loading…
Reference in new issue