Partage de minutes fail

Merci pour le partage et surtout d’avoir pris le temps de faire un bout de code qui reproduit le problème.

Pour ma part, j’ai mis environs 10 minutes à trouver le problème, et j’apprends quelque chose sur la syntaxe python.

C’est le moins qu’on puisse dire.

1 « J'aime »

@thierry.f.78, merci pour ce retour très cool.

1 « J'aime »

Alors comme tu le sais probablement je suis un énorme fan de Rust, donc j’ai tendance à être plutôt d’accord avec toi.

Ton commentaire m’a donné une idée, à partir de python 3.5, il y a les type hints pour définir du typage optionnel: PEP 484 – Type Hints | peps.python.org.
Bref qu’est ce que ça donne si j’ajoute du typage ?

Le code avec du typage (pas partout):

# bug.py
from datetime import datetime, timezone
import unittest
from typing import Dict, List, Any

class Share():
    instance_uuid = None
    share_id = None
    status = None
    tag = None
    export_location = None
    share_proto = None


def map_to_share_object(share: Share,
                        fields: List[str],
                        db_share: Dict[str, Any]):
    for field in fields:
        setattr(share, field, db_share[field])

def main()->None:
    NOW = datetime.now(timezone.utc)
    share = Share()

    fake_db_share = {
        'created_at': NOW,
        'updated_at': None,
        'deleted_at': None,
        'deleted': False,
        "id": 1,
        "instance_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",

        "share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "status": "attaching",
        "tag": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "export_location": "10.0.0.50:/mnt/foo",
        "share_proto": "NFS",
    },

    fake_instance = {
        "instance_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
        "instance_flavor": "tiny"
    }

    map_to_share_object(share,
              [
                  "instance_uuid",
                  "share_id",
                  "status",
                  "tag",
                  "export_location",
                  "share_proto"
              ],
              fake_db_share)

    test = unittest.TestCase()
    test.assertEqual(share.instance_uuid,
                     'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa')
    test.assertEqual(share.share_id,
                     'e8debdc0-447a-4376-a10a-4cd9122d7986')
    test.assertEqual(share.status,
                     'attaching')
    test.assertEqual(share.tag,
                     'e8debdc0-447a-4376-a10a-4cd9122d7986')
    test.assertEqual(share.export_location,
                     '10.0.0.50:/mnt/foo')
    test.assertEqual(share.share_proto,
                     'NFS')


if __name__ == '__main__':
    main()

Ensuite je lance mypy pour faire l’analyse statique:

 🦉 rribaud  ~  workspace  bug  mypy bug.py 
bug.py:54: error: Argument 3 to "map_to_share_object" has incompatible type "Tuple[Dict[str, Union[str, int, bool, datetime, None]]]"; expected "Dict[str, Any]"
Found 1 error in 1 file (checked 1 source file)

AMHA, c’est quand même mieux.

  1. Déja on trouve le problème pas au runtime. A contrario sans le typage, si le code n’est pas éxécuté, on ne voit pas le problème. (d’ou l’importance encore plus grande des tests et de la couverture)
  2. Ca donne une information plus précise sur l’origine du problème. On sait que le soucis vient de l’argument 3.
  3. Ca “autodocumente” le code grace à la signature de la fonction.
1 « J'aime »

@remi, faut venir nous parler de ça lors d’une prochaine session de la libre antenne sur le sujet. :wink:
En + comme c’est du K8s, je suis sur que ça va intéresser plein de personnes.

1 « J'aime »

Je comprends par cette phrase que le typage de python doit être vérifié par un programme qui n’est pas python, mais qui est mypy ?

A l’occase faudra que je passe, la vie est remplie d’échecs :stuck_out_tongue:

1 « J'aime »

@thierry.f.78, oui c’est ça.

  • Python àpartir de 3.5 va accepter la syntaxe pour définir les types.
  • Par ailleurs tu vois qu’il faut un module typing pour définir les types plus complexes que string, int, etc…
  • Et effectivement un programme externe mypy qui fait la vérification. Il y a pleins d’integrations pour les éditeurs/IDEs histoire de voir les résultats dans l’éditeur/IDE et que se soit “transparent”.
1 « J'aime »

Le typing python est une vrai transformation du langage et là où les tests étaient ton seul salut, désormais le typing vient faire le job.

Oui le typing aide. Après ne laisse pas croire qu’il ne faut plus faire de tests. :stuck_out_tongue_winking_eye:

Non bien sur!
Mais certain tests deviennent redondant avec le typing, et c’est plus simple de déclarer des type que de créer un cas de test

a discuter dans le prochain numéro : Atlassian a effacé les environnements cloud de 400 clients par erreur

1 « J'aime »

Sans spoiler ça va arriver, @erwan va nous parler de ce sujet. :wink:

2 « J'aime »

Attention je ne suis pas le responsable pour atlassian :sweat_smile:

2 « J'aime »

Un potentiel sujet chez Heroku?

1 « J'aime »

Vanta (service qui aide à passer les audits de sécurité comme SOC2) a temporairement mélangé des données entre ces comptes clients (uniquement des noms de channels Slack).
En soit ce n’est pas trop critique comme fuite mais c’est assez trivial de devoir déclarer un incident de sécurité dans l’outils de suivi d’incident de sécurité.

Today Vanta became aware of a bug that caused channel names from some Slack workspaces to be temporarily available to another customer in the autocomplete dropdown of their notification settings page.

We deployed a fix 1 hour and 10 minutes after being made aware of the issue. After a comprehensive review of our logs, we believe your account was affected.

du coup d’accord 1h 10 ça va, top réactivité mais à la fin de l’email qui est hyper long … ça parle du bug et du cache résiduel We do not store this list long term, but we do cache the list for 30 seconds in Redis. bon là encore 30 seconds d’accord. Puis arrive la partie Forensics

With an understanding of the bug, we were able to review our logs from the time this bug was introduced on February 24, 2022 until the time it was fixed on April 27, 2022 for any instances where it’s possible that a customer was shown the incorrectly cached results from another Vanta account.

Ah oui quand même, donc en fait 2 mois donc :slight_smile: Et le message continue avec Response Timeline qui reprend uniquement les 1h10 du fix :slight_smile:

Mais en soit ça respecte la SLA qui se déclenche au moment où c’est découvert, reste à savoir si ils ont communiqué quand ils l’ont trouvé ou bien quand le planning permettait un fix rapide…

Oui sauf que Python ne check pas les types, c’est juste un indication:

Note
The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc.

Au même titre que les tests… si tu ne lancent pas ils ne sont pas utiles :wink:

Petite minute fail / devinette / “piège” réseau.

Un peu de contexte, j’ai un devstack (openstack de dev) installé sur une vm (Centos stream 9) de mon laptop.
Avec ce devstack je crée des VMs (nested) et j’expose une ip flottante pour accéder depuis mon devstack. Jusque-là pas de soucis je peux me connecter en ssh sur mes VMs. Par contre je n’arrive pas à installer de package sur ces VMs, en effet elles ne peuvent pas sortir sur internet. Après recherche et vérification que le nat, le forwarding, les security groups, etc… sont configurés correctement, mon hypothèse est que j’ai sur mon host une règle de firewall qui bloque le forward.
Il s’agit de la règle 2 dans la chain forward du screenshot ci-dessous.

Je me dis que pour vérifier mon hypothèse, je vais insérer une règle juste avant qui annihile la règle 2, il s’agit de la règle 1.

[stack@openstack nova]$ sudo iptables -v --list --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     146K  321M ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
2        0     0 ACCEPT     icmp --  any    any     anywhere             anywhere            
3      809 48540 ACCEPT     all  --  lo     any     anywhere             anywhere            
4        1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere             state NEW tcp dpt:ssh
5       50 17996 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      0   0     ACCEPT     all  --  any    any     anywhere             anywhere            
2      577 42665 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 147K packets, 321M bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Pour insérer cette règle, j’ai utilisé la commande suivante.

sudo iptables -I FORWARD -i any -o any -j ACCEPT

Et la, mes VMs n’accèdent toujours pas à internet. Je passe sur l’analyse et le temps pour trouver le problème, l’hypothèse se révélera être la bonne, mais forcement j’ai fait une boulette fatale !
Serez-vous la retrouver ? (énorme teasing :stuck_out_tongue_winking_eye:)

Indice: la règle 1, ne capture aucun paquet…

La règle n°5 en INPUT ?