Pages

Tuesday, 7 August 2012

Tips for writing a readable CV and cover letter

Note: those are my personal opinions and by no mean I pretend those to constitute a universal truth.

I had the chance to read several curricula over the last few years and to be honest a very tiny percentage of that was something that I found enjoyable.

The thing is when you are reviewing CVs for a position you are facing a hard situation: there are something like 100-150 persons that want your attention and you already know that 70% of that will not be a good candidate (of course the odds might be better or worse depending on many factors, but as a rule of thumb that's what I found out).

So you allocate some time (usually a full day at least) to read those 150 CVs (you already know you will never make it), make a day 8 hours, that makes 3 minutes per each CV with no pauses and no interruptions. Of course the reality is that it takes 3 minutes maybe to read it, then another 5 to 7 at least to understand it, evaluate it, take some notes and decide what to do with it.

But anyway let's assume that a normal reviewer really has 3 minutes to dedicate to your CV (and cover letter).

What do you think it's the reaction when the guy sees 5 pages of CV? Three possible reactions: procrastination (you will go to the end of the queue), drop (you will never get read), evaluation (the guy is in a really good mood).

So first tip: make it 2 (two) pages. No reviewer has time to read your 5 pages CV.

Actually the first thing that a reviewer will read is your cover letter. That's even more important than the CV.

A good cover letter is something that tells the 3 essential thing about you to the guy who's about to read your CV. Is kind of a preparation to your CV. Think you are going on the stage in front of 1000 people. What do you want these 1000 people remember about you?

You think that "Hi, please find attached who I am" would work? Or "I am very interested in any position you might have to offer" works better?

Yeah I think you understood. You have to go there on the stage and be a freaking rock star (everybody knows there is only a limited amount of rock stars in the world).

Engage the reader, tell him really who you are and what great things you have done. Don't lie. Don't try to "I am sure you will agree with me when I say..." or quote Steve Jobs or give great names to tiny things. Be yourself, the real yourself. Tell them your story. That's what the guy wants to know: "Who the heck is this guy?"

So a cover letter should shortly say (e.g.):

"Hi there,

I found this rocket scientist position interesting because I love rockets. Rockets are all I ever wanted to do and there is nothing that will ever stop me from doing them.

I was graduated by the Rocket Science academy in Williwonkaland and since then I worked for 14 yrs in a garage building my own rocket. It flies, it went to the moon but never came back. But I did it all by myself.

You might think I am crazy but I am just a rocket scientist that wants to work with you."

Lately (and for the first time in my experience) I read a very nice cover letter. I don't remember the CV but I remember the guy because of the cover letter. This is what you want to happen.

Of course the cover letter has to be short and concise and exactly to the point. Use a big font and colors if you want as long as you say the right things in the right tone.

Of course if you are a musician and you applied to a rocket scientist position don't hold your hopes.

So second tip: Write a gorgeous cover letter. Short and to the point where you say why you like to work in this position and for this company.

Ok back to the CV.

What does the CV have to have?

Your name and contact details and where you are located (city, nobody cares about your address).

Who you are (even if you put it already in the cover letter). This has to be a one liner, something that should help the reviewer understand if she has to continue reading or stop there.

Example: "Rocket scientist with 14 yrs experience of building rockets in own garage"

Then write there where you got this experience. What you have done more than 10 years ago (unless is still your current job) does not matter. You have forgotten it, our brain does not have that much memory.

So third and last tip: write there your latest ( < 10 yrs) experiences

Per each position write your title, for what company (if you can disclose it), what was your assignment and 1 (one) important (really important) thing that you have done. Eventually links to proof of your work or portfolio. Order the positions you held in reverse order (from latest to oldest).

Example:

2005 - 2010 Cleaning manager at YMCA
 -  In charge of cleaning windows and floors. Once people were brushing looking their image on the floor so much it was clean. [Photos of the floor at Flickr]
2000 - 2005 Cleaning manager at ACME
 - In charge of cleaning all the windows. Once cleaned 73 windows in one day.

Then your education (only the most important/s, nobody cares about your primary school).

Then if you really want (but not many read them) your interests.

That's it.

This is of course if you want to have a "standard" CV. If you want to do something else (a PPT, a flash animation, a movie, comics, ...) then you are already different and you will already catch the attention of the reviewer. So ignore the tips in that case.

Tuesday, 29 May 2012

How to add a new schema to openLDAP 2.4+

I tried to stay away from the new config type in LDAP introduced in v.2.3 as much as I could but today I had to face it.

I understand the reasons behind but I have to say that the docs are pretty scarce and any newbie has a pretty steep learning curve ahead especially if used to the old way of configuring LDAP.

The configuration now is in ldif format and it follows a pretty logical scheme which is clearly shown in this picture
What you find inside these trees (which are also directories inside /etc/ldap/slapd.d dir) is all your LDAP server knows about, all the rest in the /etc/ldap is not really that interesting.

Anyway you are to read something else, I know. I could not honestly find a straight answer to the question which gives the title to this post, even though there are a lot of places that contain bits of info but as usual the amount of work needed to get everything in place is still some. That's why I am writing this post.

[UPDATE: just found this which is pretty close to what I needed.]

I will start with a practical real-life example: Adding the sshPublicKey schema kindly provided here to your LDAP server. [I am basing my example on a Debian Squeeze installation]

Now you will find in /etc/ldap/schema/ a lot of .schema files. And there is where you will start to get confused... so forget the schema files.

Copy paste the openssh-lpk_openldap.schema in /etc/ldap/schema/ directory (just to keep them happy together):
#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE <eau@phear.org>
# 
# Based on the proposal of : Mark Ruijter
#


# octetString SYNTAX
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' 
 DESC 'MANDATORY: OpenSSH Public key' 
 EQUALITY octetStringMatch
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )

# printableString SYNTAX yes|no
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
 DESC 'MANDATORY: OpenSSH LPK objectclass'
 MAY ( sshPublicKey $ uid ) 
 )

Create a tmp directory, e.g. /tmp/ldapstuff and create a dummy file there called for instance slapd.conf which simply has this line
include /etc/ldap/schema/openssh-lpk_openldap.schema
Run
cd /tmp/ldapstuff && slaptest -f slapd.conf -F .
This will create in place a dir called cn=config and a file cn=config.ldif.

Run
cd cn=config/cn=schema && vim cn={0}openssh-lpk_openldap.ldif 
 The only interesting things that need to stay in that file are the  following:
dn:
cn:
objectClass:
olcAttributeTypes:
olcObjectClasses: 
So remove everything else and edit dn and cn. This is a schema so it will need to be inside the cn=schema,cn=config LDAP tree, so the result should be
dn: cn=openssh-lpk_openldap,cn=schema,cn=config
cn: openssh-lpk_openldap
Now you are ready to add this to your LDAP server:
ldapadd -Dcn=admin,cn=config -W -f /tmp/ldapstuff/cn=config/cn=schema/cn={0}openssh-lpk_openldap.ldif
That's it, you can verify that it's really there by
ldapsearch -xLLL -D cn=admin,cn=config -W -b cn=config cn=*ssh*
This should give you some result. This is pretty much applicable to any other schema.

Monday, 24 October 2011

Regaining access to an AWS (Amazon) Linux machine

Say you secured so much your AWS server you can only login with SSH keys there. And you have only one SSH key that can access that server. And you lost your SSH key or forgot the passphrase for it.

Are you damned to lose all that work you have poured into that machine? Probably not, if you have the luxury of some downtime.

AWS does not have any (easy) way to just change the SSH key that can access to a system.

So after 30 minutes of attempts this is how I managed to get access back to my machine.
  1. Create another machine (a copy or just a new one it doesn't matter) and start it up. Pay attention to authorize a new SSH key that works to access this machine.
  2. Shut down the original machine
  3. Detach the (root) disk volume
  4. Attach that volume to the running instance
  5. mount the root partition (running dmesg or fdisk -l will tell you what to mount)
  6. go to <mtpoint>/root/.ssh/
  7. vi authorized_keys and add there the public key of your new key
  8. shutdown this new machine
  9. detach the volume
  10. reattach it to the old instance
  11. restart the instance and ssh into it with the new key

Be happy.


Ps. I found here another method involving snapshots but I just couldn't make it work. For some reason the cloned machine was always empty.

Saturday, 27 August 2011

Buying group - Goodstuff from Italy

To all my friends in Finland (if I didn't send you an email already): it's that time of the year.

If interested in good food from Italy go and fill the webform (now improved usability!)

http://bit.ly/omRLY2

I hope to have all the orders by mid September (in 3 weeks), place the order in 4 and get the stuff within the second week of October. If everything goes fine :)

Wednesday, 22 June 2011

N9 - Against all odds

Well it wasn't (and it's still not) easy to run the IT behind harmattan/N9. But we made it. And the feedback on the device is just bursting for us behind the scenes. The whole Nokia/MeeGo team has pulled off a beautiful device against all odds. It's true that difficulties makes you stronger.

I am proud of all my team and all my colleagues.

Thank you all for making it the most challenging and beautiful experience of my carreer.

Monday, 25 April 2011

Calling only once setUp in unittest in python

In python unittest the setUp function gets called every time you need to run a single TestCase (no matter if you run it using TestSuite or simply unittest.main()).

So if you have to test something that requires a complex setUp routine (like loading 50000 records from SQL or preparing an orangemochafrappuccino) but that can be reused all along your TestSuite you have the same problem I had.

Now all around the internet there are posts saying "You could do that" or "One way to do that" or "Once I did that like this..." or even worse "The standard way of doing it is...".

But none of these posts really gets to the bottom of it, they all give you a piece of information. I couldn't find one place that told you "copy/paste this code and be happy".

So, after figuring it out, I can now tell you "copy/paste this code and be happy".
import unittest
from my_program import MyClass

class MyClassTest(unittest.TestCase):
    # First define a class variable that determines 
    # if setUp was ever run
    ClassIsSetup = False

    def setUp(self):
        # If it was not setup yet, do it
        if not self.ClassIsSetup:
            print "Initializing testing environment"
            # run the real setup
            self.setupClass()
            # remember that it was setup already
            self.__class__.ClassIsSetup = True
                               
    def setupClass(self):
        # Do the real setup
        unittest.TestCase.setUp(self)
        # you want to have persistent things to test
        self.__class__.myclass = MyClass()
        # (you can call this later with self.myclass)

You can do the same for the unittest.tearDown since it is exactly the same code.

Mocking LDAP calls with minimock in python

When using unittest in python you often need to mock objects and calls to those objects.

You don't need _an_entire_ LDAP server just to test a search nor you need a full blown SMTP server to test a function that accidentally sends a mail (that you don't want to send while testing anyway).

So minimock is one easy way (the easiest I found) to do the job.

What the docs don't really tell you (nor does a google search) is how to return real things when you need to call a method of an object.

Say you have some code like this:
import ldap
class MyClass:
...
    def ldapsearch(self, uid):
        self.conn = ldap.open(self.conf.ldapserver)
        self.conn.bind_s(binddn, bindpw, ldap.AUTH_SIMPLE)
        self.conn.search_s(basedn, ldap.SCOPE_SUBTREE, 'uid=%s' % uid, ['uid'])
        return True

and you want to test this and moreover you want that search to return a given set of data.

from minimock import Mock
import ldap
from my_program import MyClass

class MyClassTest(unittest.TestCase):
...
    def test_ldapsearch(self):
        # create your fake ldap connection
        ldap.open = Mock('ldap.open')
        ldap.open.mock_returns = Mock('ldap_connection')
        # instantiate your class
        myclass = MyClass()
        # now tell to minimock that in case we do a search_s on 
        # a conn method this should be intercepted and mocked
        # returning a testuser1 value the way LDAP would do
        myclass.conn.search_s.mock_returns = [[1,{'uid':['testuser1'], \
                                        'mail':['test.user1@mail.com']}]]
        # This will return testuser1 no matter what
        # and show you on screen the operations performed
        self.assertEqual(myclass.ldapsearch('onetwoonetwo'), True)

This should help you inject whatever values you want there and also clarify a bit how to minimock wants you to think (that is the only way I could make it work).