Mein Abschied von ampad

Adrian Yass, 18 Dez 2016

“Beileid, ihr seid jet­zt ver­heir­at­et.” Ver­heir­at­et? Ich? Am 01.04.2010? Aprilscherz? Naja, nicht ganz. Nur ein bis­schen Sar­kas­mus eines Fre­undes. Raphael und ich saßen gerade bei der Volks­bank und hat­ten ein ge­mein­sames Konto eröffnet: Un­ser Firmen­konto. Denn am 01.04.2010 wurde die am­pad UG (haf­tungs­bes­chränkt) & Co. KG ge­boren. Kein Aprilscherz. Und um es kurz zu machen: Das Kind ist jet­zt 6 Jahre und 9 Mon­ate alt. Alt genug um eingeschult zu wer­den und alt genug um auf ei­gen­en Bein­en zu stehen.

Ich selbst habe die let­zten Jahre viele Pro­jekte par­al­lel ge­habt. Ver­mut­lich zu viele gleichzeit­ig. Für mich ist es Zeit, meine En­er­gie konzentriert ein­zu­set­zen. Und so habe ich beschlossen diese Firma ihren ei­gen­en Weg ge­hen zu lassen.

Und das wird sie auch. Sie steht gut da. An ihr­er Spitze sehe ich mit Raphael Kim­mig ein­en zuverlässigen, ver­trauenswürdi­gen und ehr­lichen Geschäftsführ­er und ein­en guten Fre­und. Mit ihm kann ich mir sich­er sein, dass er sich gut um sie kümmern wird und sie sich weit­er­entwick­eln kann. Und je­mand, den ich un­einges­chränkt weit­er­em­p­fehlen kann.

Am­pad ist keine riesen­große Firma, trotzdem hat sie ein beacht­liches Wach­stum hingelegt und eine be­merkenswerte Sta­bilität. Alles was diese Firma hat, hat sie sich selbst erarbeiten müssen. Wir haben uns ohne Förder­ung gegründet, ohne Kred­ite, ohne Inkubat­or, der uns Strom, Wasser, In­ter­net, oder auch nur ein Dach über dem Kopf fin­an ...

continue reading

We re­cently needed a way to run mul­tiple ap­plic­a­tions us­ing cel­ery + rab­bit­mq on the same serv­er. For­tu­nately rab­bit­mq of­fers vhosts to isol­ate cli­ents and set­ting them up is quite easy. The setup we are go­ing for looks as fol­lows

  1. Have one rab­bit­mq vhosts for each django ap­plic­a­tion.
  2. Run an in­stance of cel­eryd for each django ap­plic­a­tion.

For each of our apps djan­goap­p01 … djan­goappN we do the fol­low­ing

Adding a vhost to rab­bit­mq ist simple

rabbitmqctl add_vhost /djangoapp01

Now we need to add a user and grant per­mis­sions to the vhost

 rabbitmqctl add_user djangoapp01 <password>

 rabbitmqctl set_permissions -p /djangoapp01 djangoapp01 ".*" ".*" ".*"

Now we need to set up cel­ery. We use the init script sup­plied in cel­ery ex­tra (ht­tps://git­hub.com/cel­ery/cel­ery/blob/3.1/ex­tra/gen­er­ic-init.d/cel­eryd) which has sup­port for run­ning mul­tiple con­fig­ur­a­tions by re­nam­ing it. We copy that file to /etc/init.d/cel­ery­d_d­jan­goap­p01 and cre­ate an ap­pro­pri­ate cel­ery con­fig file in /etd/de­fault/cel­ery­d_d­jan­goap­p01

In the set­tings.py for djan­goap­p01 we make sure to set

BROKER_URL = 'ampq://djangoapp01:<password>@localhost//djangoapp01'

When you want to run mul­tiple django ap­plic­a­tions us­ing cel­ery on the same serv­er you need some way to sep­ar­ate the work queues. And you should be good to go.

If you are in­ter­ested, we use the ans­ible con­fig be­low to set up rab­bit­mq and cel­ery ac­cord­ingly:

 - name: set up rabbitmq vhost
   rabbitmq_vhost: name="/{{ deploymentname }}" state=present
 - rabbitmq_user: user="{{ deploymentname }}"
                  password="{{ rabbitmq_password }}"
                  vhost="/{{ deploymentname }}"
                  configure_priv=.*
                  read_priv=.*
                  write_priv=.*
                  state=present
 - name: set up celeryd
   template: src=celeryd_init dest="/etc/init.d/celeryd_{{ deploymentname }}" mode=755
 - template: src=celeryd_default dest="/etc/default/celeryd_{{ deploymentname }}"
   notify:
     - restart celery

Oblivious to the obvious

Raphael Kimmig, 28 Sep 2013

Just be­cause I've just spent half an hour tra­cing through WebTest and the Django au­th in­tern­als...

When you are us­ing WebTest to test cus­tom ad­min views and for some reas­on your user lo­gin doesn't seem to work - make sure to check for is_staff=True on the test user.

from django_webtest import WebTest
from django_dynamic_fixture import G

class CustomAdminTest(WebTest):
    def setUp(self):
        self.user = G(User, is_superuser=True, is_staff=True)

    def test_custom_admin_page(self):
        custom_page = self.app.get(reverse('admin:custom_page'), user=self.user)
        self.assertContains(custom_page, 'custom value')

When test driven design makes things worse

Raphael Kimmig, 30 Jul 2013

Today I watched an in­tro­duc­tion to test driv­en design us­ing an­gu­lar.js' test­ing tools.

In gen­er­al it is a nice in­tro­duct­ory talk, however one of the ex­amples used got me think­ing. The scen­ario (about 33 minutes in­to the video) is a no­ti­fi­er class that batches no­ti­fic­a­tions and sends them to the user when a cer­tain lim­it is hit.

Notifier.send = function (user, message) {
     var email = user.getDetails().email
     // enqueue email + message for eventual delivery by the backend
     ...
}

Now it is reasoned that the no­ti­fi­er hav­ing to know about the user's in­tern­al struc­ture is a bad thing (mak­ing a ref­er­ence to the law of De­meter). This leads to the fol­low­ing re­fact­or­ing at about 33:45.

Notifier.send = function (email, message) {
     // enqueue email + message for eventual delivery by the backend
     ...
}

I'd guess the real mo­tiv­a­tion for chan­ging this is the fact that when test­ing the send meth­od you need to stub out a user ob­ject to­geth­er with the de­tails. This makes the test look worse and thus cre­ates an in­cent­ive to find an­oth­er solu­tion.

Don't get me wrong, the sig­na­ture change def­in­itely has an ad­vant­age. The no­ti­fi­er doesn't need to know about the user at all - but there are some draw­backs to this:

  1. The no­ti­fi­er will nev­er be able to send no­ti­fic­a­tions via any­thing but email (which would be a per ...
continue reading

Yes­ter­day I was search­ing for a way to check­out Git­Hub pull re­quests and re­view them loc­ally that is more con­veni­ent than adding new re­motes.

For­tu­nately Fil­ippo Valsorda doc­u­mented how you can fetch a pull re­quest via

git fetch origin refs/pull/PR_NUMBER/head:LOCAL_BRANCH

Be­cause I like ali­ases I cre­ated this little ali­as which goes in­to your ~/.git­con­fig

[aliases]
pr = !sh -c '(test -n \"$1\" -a -n \"$2\" && \
      git fetch origin refs/pull/$1/head:pr_$1_$2) || \
      echo \"usage: git pr pull_request_number branch_name\"' -

This al­lows you to do

git pr 37 usablitiy_improvements

which will check out the Git­Hub pull re­quest num­ber 37 in­to a loc­al branch pr_37_usabilitiy_improvements where you can do whatever you'd like to do with it.