Projet

Général

Profil

0002-mdel-add-SFTP-connection-options-to-send-and-receive.patch

Serghei Mihai (congés, retour 15/05), 27 janvier 2021 10:37

Télécharger (5,99 ko)

Voir les différences:

Subject: [PATCH 2/2] mdel: add SFTP connection options to send and receive
 demand file (#50543)

 .../migrations/0006_auto_20210126_1440.py     | 26 +++++++++++++
 passerelle/apps/mdel/models.py                | 38 +++++++++++++++++++
 tests/test_mdel.py                            | 20 ++++++++++
 3 files changed, 84 insertions(+)
 create mode 100644 passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py
passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.29 on 2021-01-26 13:40
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations
6
import passerelle.utils.sftp
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('mdel', '0005_remove_mdel_log_level'),
13
    ]
14

  
15
    operations = [
16
        migrations.AddField(
17
            model_name='mdel',
18
            name='incoming_sftp',
19
            field=passerelle.utils.sftp.SFTPField(blank=True, default=None, verbose_name='SFTP server for incoming files'),
20
        ),
21
        migrations.AddField(
22
            model_name='mdel',
23
            name='outcoming_sftp',
24
            field=passerelle.utils.sftp.SFTPField(blank=True, default=None, verbose_name='SFTP server for outgoing files'),
25
        ),
26
    ]
passerelle/apps/mdel/models.py
24 24
from passerelle.base.models import BaseResource
25 25
from passerelle.compat import json_loads
26 26
from passerelle.utils.api import endpoint
27
from passerelle.utils.files import atomic_write
27 28
from passerelle.utils.jsonresponse import APIError
29
from passerelle.utils import SFTPField
28 30

  
29 31
from . import mdel
30 32

  
......
74 76
    - Acte d'Etat Civil (AEC-LA)
75 77
    - Recensement Citoyen Obligatoire (RCO-LA)
76 78
    """
79

  
80
    outcoming_sftp = SFTPField(verbose_name=_('SFTP server for outgoing files'), blank=True)
81
    incoming_sftp = SFTPField(verbose_name=_('SFTP server for incoming files'), blank=True)
82

  
77 83
    category = _('Civil Status Connectors')
78 84

  
79 85
    class Meta:
......
120 126

  
121 127
        demand.save()
122 128

  
129
        if self.outcoming_sftp:
130
            self.add_job('send_demand', demand_id=demand.demand_id)
131

  
123 132
        return {'data': {'demand_id': demand.demand_id}}
124 133

  
125 134
    @endpoint(perm='can_access')
......
161 170
        return os.path.join(mdel.get_resource_base_dir(),
162 171
                            self.slug, 'outputs')
163 172

  
173
    def send_demand(self, demand_id):
174
        try:
175
            demand = Demand.objects.get(demand_id=demand_id)
176
        except Demand.DoesNotExist:
177
            return
178
        with self.outcoming_sftp.client() as client:
179
            client.put(demand.filepath,
180
                       os.path.join(client.getcwd(), demand.filename))
181

  
182
    def get_response_files(self):
183
        if not os.path.exists(self.output_dir):
184
            os.makedirs(self.output_dir)
185

  
186
        with self.incoming_sftp.client() as client:
187
            for filename in client.listdir():
188
                if filename in os.listdir(self.output_dir):
189
                    continue
190
                with atomic_write(os.path.join(self.output_dir, filename)) as fd:
191
                    client.getfo(filename, fd)
192

  
193
    def hourly(self):
194
        super().hourly()
195
        if self.incoming_sftp:
196
            self.get_response_files()
197

  
164 198

  
165 199
@six.python_2_unicode_compatible
166 200
class Demand(models.Model):
......
194 228
    def filename(self):
195 229
        return '%s.zip' % self.name
196 230

  
231
    @property
232
    def filepath(self):
233
        return os.path.join(self.resource.input_dir, self.filename)
234

  
197 235
    def create_zip(self, formdata):
198 236
        """
199 237
        Creates demand as zip folder
tests/test_mdel.py
31 31
from passerelle.apps.mdel.mdel import Message, Description, AttachedFile, get_resource_base_dir
32 32
from passerelle.apps.mdel.utils import parse_date
33 33
from passerelle.compat import json_loads
34
from passerelle.utils import SFTP
34 35

  
35 36
import utils
36 37

  
......
305 306
        assert root.find('DemandeActe/Titulaire/Filiation/Pere/Prenoms').text == 'Ryu'
306 307

  
307 308

  
309
def test_create_aec_demand_with_output_sftp(app, setup, aec_payload, sftpserver):
310
    setup.outcoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/output/'.format(server=sftpserver))
311
    setup.save()
312
    resp = app.post_json('/mdel/test/create', params=aec_payload, status=200)
313
    expected_filename = '%s-0.zip' % resp.json['data']['demand_id']
314
    with sftpserver.serve_content({'output': {expected_filename: 'content'}}):
315
        setup.jobs()
316

  
317

  
318
def test_create_aec_demand_with_input_sftp(app, setup, aec_payload, sftpserver):
319
    setup.incoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/input/'.format(server=sftpserver))
320
    setup.save()
321
    resp = app.post_json('/mdel/test/create', params=aec_payload, status=200)
322
    expected_filename = '%s-1.zip' % resp.json['data']['demand_id']
323
    with sftpserver.serve_content({'input': {expected_filename: 'content'}}):
324
        setup.hourly()
325
    assert expected_filename in os.listdir(setup.output_dir)
326

  
327

  
308 328
def test_create_aec_demand_type_without_date_acte(app, setup):
309 329
    payload = json_loads(get_file_from_test_base_dir('formdata_aec_deces.json'))
310 330
    payload['fields'].pop('date_acte')
311
-