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