miércoles, 4 de abril de 2018

Making MongoDB remotely available.




Summary

Here I show how to make your MongoDB accessible from a different server / computer/ instance, without using ssh.

Motivation

I have been using MongoDB to store and query some databases. This databases has been shared with other people and in most of the cases I have managed to use it as localhost or using ssh. However when using Docker it is easy to run into problems when using ssh. It is common to access other databases such as MySQL.

For example in to use MySQL in Python you could have something like this:
import pymysql.cursors

# Connect to the database
connection = pymysql.connect(host='localhost',
                             user='user',
                             password='passwd',
                             db='db',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

In the same line you could query your MongoDB using PyMongo
    import pymongo
    from pymongo import MongoClient
    client = MongoClient('localhost',27017)
    db = client[database_name]

where 'localhost' is just your machine, or '127.0.0.1'. Also you could use a Mongo URI . For example:
client = pymongo.MongoClient("mongodb://tom:jerry25K@35.178.145.134:27017"),
where you are saying to pymongo,  the host: 35.178.145.134, the user: tom, the password: jerry25K.

Fair enough, but how to have this or similar into place?. This is the key point here. So you can use your MongoDB from a remote computer.

Two cases


We should discuss first a little bit about security. Do you want to have a user with the password? Do you want to open the ports of you MongoDB server?

Probably the most secure here is to grant access from some particular IPs and to have a user with a password. However I will cover both so you choose. For example, you may not have permissions to create new users.


Open ports and NO user with password
You should grant access from the database and from the server.

  1. From the database. MongoDB by default can only be accessible from localhost. There are different ways to overcome that. I suggest to modify the configuration file.
    1. sudo vim /etc/mongod.conf
    2. Go to "network interfaces", the default will be 127.0.0.1, just change that to 0.0.0.0
With this you are saying to MongoDB to listen to every available network interface [Ref].

    1. After that, please restart you MongoDB: sudo service mongod restart.




Now you should open the port 27017 (where MongoDB is working to external access).  Usually when you query an IP you may not have access so you need to have access first to the database. If you are in AWS you can follow the next steps, [from here].
  • Go to your EC2 dashboard: https://console.aws.amazon.com/ec2/
  • Go to Instances and scroll down to see your instance’s Security Groups. Eg, it will be something like launch-wizard-4
  • Go to Netword & Security -> Security Groups -> Inbound tab -> Edit button.
  • Make a new Custom TCP on port 27017, Source: Anywhere, 0.0.0.0/0
Now you should be able to query your database without problems. To check it you could use Robo3T. Here a snapshot from a query using Python 2.
JOB DONE!
Open ports and WITH user with password

This option include the previous one. So you should do the previous one before you continue here.

Go back to the configuration file and allow for authorization.
  1. sudo vim /etc/mongod.conf
  2. Create another user. Here I put two different scenario. A simple user or a SuperUser:
    1. Create a user with access to a database, borrowed from https://ianlondon.github.io/blog/mongodb-auth/: 
    2. Superuser: here the steps https://stackoverflow.com/a/34634554/7127519. I chose this one because I amp playing around with an old snapshot I will destroy inmediately, so noone care really.
    3. You could create many different types of user, here some examples https://docs.mongodb.com/manual/reference/method/db.createUser/.
  3. Enable Security:
    1. Before, you may find something like this or just empty 
    2. After, you should uncomment and add: 
    3. Now you are enable the authorization. 
  4. Do not forget to restart to activate the changes by restarting the database: sudo service mongod restart.

Let see, as before you could check using Robo3T, probably easier.:
So there you see two of my databases.
Job Done!

My environment


I have been using Ubuntu 16.04. I have check this in a local installation and in AWS. Python 2.

References


  1. A post similar to this one. However I also talk about the possibility of not use or create a user and there is a type here, in this post the author suggest to remove the bindIP while here just to change to 0.0.0.0, in my case the first option didn't work. Something share with other people as you can read in the comments. Nevertheless a excellent post:  https://ianlondon.github.io/blog/mongodb-auth/ 
  2. If you want to create roles withing you MongoDB, here there is a excellent post to help you. It distinguis also depending of the version of your MongoDB: https://stackoverflow.com/a/34634554/7127519 
  3. How to create your users in MongoDB, great post: https://stackoverflow.com/a/34634554/7127519 . 



miércoles, 13 de diciembre de 2017

Decorators/wrappers

Decorators/wrappers




What is it?

In object-oriented programming, the decorator pattern (also known as Wrapper, an alternative naming shared with the Adapter pattern) is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.




Example for my case:
# Decorators
from functools import wraps


def my_logger(orig_func):
   import logging
   logging.basicConfig(filename='{}.log'.format(orig_func.__name__), level=logging.INFO)

   @wraps(orig_func)
   def wrapper(*args, **kwargs):
       logging.info(
           'Ran with args: {}, and kwargs: {}'.format(args, kwargs))
       return orig_func(*args, **kwargs)

   return wrapper


def my_timer(orig_func):
   import time

   @wraps(orig_func)
   def wrapper(*args, **kwargs):
       t1 = time.time()
       result = orig_func(*args, **kwargs)
       t2 = time.time() - t1
       print('{} ran in: {} sec'.format(orig_func.__name__, t2))
       return result

   return wrapper

import time


@my_logger
@my_timer
def display_info(name, age):
   time.sleep(1)
   print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('Tom', 22)


Related concepts

  1. First class functions: allow us to treat functions and any other objects, i.e. as an argument for a function, return functions, assign function to variables. Tutorial: https://www.youtube.com/watch?v=kr0mpwqttM0
  2. Closures: allow us to pass function with remember local variables. Tutorial: https://www.youtube.com/watch?v=swU3c34d2NQ

First class function (FCC)

  1. The distinction is not that individual functions can be first class or not, but that entire languages may treat functions as first-class objects, or may not.
  2. A first-class function is not a particular kind of function.
  3. All functions in Python are first-class functions. To say that functions are first-class in a certain programming language means that they can be passed around and manipulated similarly to how you would pass around and manipulate other kinds of objects (like integers or strings).
  4. "First-Class Functions" (FCF) are functions which are treated as so called "First-Class Citizens" (FCC).
  5. FCC's in a programming language are objects (using the term "objects" very freely here) which:
    1. Can be used as parameters/arguments for another functio
# Python program to illustrate functions
# can be passed as arguments to other functions
def shout(text):
   return text.upper()

def whisper(text):
   return text.lower()

def greet(func):
   # storing the function in a variable
   greeting = func("Hi, I am created by a function passed as an argument.")
   print greeting

greet(shout)
greet(whisper)
Run on IDE Output

HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
hi, i am created by a function passed as an argument.
    1. Can be used as a return value
    2. Can be assigned to variables


# Python program to illustrate functions
# Functions can return another function
def create_adder(x):
   def adder(y):
       return x+y
   return adder
add_15 = create_adder(15)
print add_15(10)


    1. Can be stored in data structures such as hash tables, lists, ...

References


Closure

Summary: you can return a function without executing by omitting parentheses.


def print_msg(msg):
# This is the outer enclosing function


   def printer():
# This is the nested function
       print(msg)


   return printer  # this got changed


# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()


When do we have a closure?


As seen from the above example, we have a closure in Python when a nested function references a value in its enclosing scope.

The criteria that must be met to create closure in Python are summarized in the following points.

We must have a nested function (function inside a function).
The nested function must refer to a value defined in the enclosing function.
The enclosing function must return the nested function.

References

  1. https://www.programiz.com/python-programming/closure
  2. https://en.wikipedia.org/wiki/First-class_functionhttps://en.wikipedia.org/wiki/Decorator_pattern#Motivation

Videos

  1. Useful tutorial with examples for timing and created logs. https://www.youtube.com/watch?v=FsAPt_9Bf3U


Blogs


martes, 5 de diciembre de 2017

How to create a function in python to be used from the terminal



To write a python code able to read variables or inputs from the command line you only have to use sys.argv. Let's see a couple of examples.

You can find the code here.


File called example_v1.py:

import sys
def main():  
    print sys.argv
    
if (__name__ == "__main__"):  

    main();


Then you go to the folder where you have it and run this comman in the comman line:


python example_v1.py

Like here:
As you can see the output is the name of the file.

Let's try this:


python example_v1.py  hi hola ciao


Basically the comand sys.argv is giving us a list of the commandline arguments received.


Now I am going to create a program that is going to say hi and the name that you introduce after file name in the commandline. I called this script example_v2.py:

import sys
def main():  
    print 'Hi ' + sys.argv[1] + '!'
    
if (__name__ == "__main__"):  

    main();

So now we can write in the terminal:


python example_v2.py  Eduard

This is the result:



References:

  • This tutorial is largely inspired in https://www.youtube.com/watch?v=DCxYAYzTWOI&t=677s.
  • To see sys.argv: http://www.pythonforbeginners.com/argv/more-fun-with-sys-argv 


sábado, 13 de mayo de 2017

La broma de la estiba y como funcionan las cosas en España




Muchas gente en Inglatera me pregunta cómo puede ser que en España hayan esas tasas de paro en torno al 25% y la verdad es que es dificil de explicar. Sobre todo para gente que esta acostrumbrada al mercado de trabajo inglés.

Para empezar el mercado de trabajo en inglaterra es muy flexible. 

a) Hay variaciones de salarios atendiendo a las situaciones personales de cada uno, es decir, si uno es muy bueno en su trabajo podrá ganar más que otra persona que no lo he es tanto o no se esfuerza. Generalmente tu "manager" sabe muy lo que haces y lo que no, tu eficiencia e interes y tienes posibilidades de promocion y formacion en la misma empresa/universidad/escuela. Trabajes dónde trabajes hay gente.

b) De la misma manera si la empresa no esta contenta contigo aunque no te despida no te volverá a contratar.

A priori estas dos cosas pueden parece que son idénticas, pero el sentido de a) y b) es totalmente distinto en uno y otro. Por ejemplo conozco a muchos profesores en España que pueden trabajar mucho pero que no van a tener ninguna mejora salarial, mientras que en Inglaterra tu al final de año puedes hablar con tu supervisor y claramente pedir un aumento siempre que lo justifiques. De lo contrario siempre puedes encontrar otro trabajo.

En España puedes pedir, pero las posibilidades de incrementar tu salario son menores, porque a lo mejor eres funcionario, o porque la empresa simplemente no quiere. Quizá tu no te atrevas a pedir un aumento porque hay mucho paro y sea dificil encontrar otro trabajo. Sin embargo, si tu estas realizando un trabajo con resultados reales para la organización a la que pertenezcas siempre se tenderá a valorar esto de alguna manera. Desde luego en inglaterra es más flexible.

En España las empresas evitaran despedir empleados de larga duración, porque es caro, pero siempre podrán despedir empleados más precarios porque es muy muy barato. Aquí hay un enorme conflicto de intereses y al final se llega a que las personas con mejores trabajos tiendar a mantenerlos mientras que las personas con reciente incorporación no. En Inglaterra también hay algo así, pero en general la empresa se quedará con la opción más rentable a medio plazo.

Dicho esto es muy dificil encontrar en Inglaterra situaciones tales cómo lo que se da en España con la estiba. Es casi imposible que en Inglaterra hayan sectores de gente que ganen máxivamente más dienro (que de una u otra forma sus puestos de trabajo esten mucho mejor/sean más seguros que otros grupos similares).

Sin embargo en España nos encontramos con cosas cómo la estiba (mirá aquí) cuyos salarios medios son más del doble que la media, incluso por encima de colectivos con muy buena formación como los médicos (ver aquí). ¿Cúal es la causa para estos salarios? Pues no lo sé he intentado leer la página web de los estibadores pero sigo sin pista (ver aquí).

Parece además que a nivel europeo no somos los más baratos (ver aquí).

La única explicación que se me ocurre es que un pequeño colectivo a ido acumulando privilegios y privilegios a traves del tiempo y por supuesto ahora es muy dificil desprenderse de estos privilegios incluso cuando su salario medio es más del doble de la media, incluso cuando hay millones de parados. M

Menos mal que la Unión Europea y sus instituciones bienes al rescate de manera que estas situaciones, en las que un pequeño colectivo tiene un control enorme de manera injustificada no pasa desapercibida y obliga al gobierno a revisar esta situación.

Pero esta no es la única situación. Bajo la idea del respeto a los derechos a los trabajadores muchas veces nos olvidamos del repeto al derecho a los no trabajadores, porque estan en paro. De la misma manera estas situaciones nos hacen más ineficientes e incrementan los precios de manera injusta y desproporcionada.

Esta no es la única situación, ahí tenemos a las farmacias, hay tenemos a los notarios, a los controladores aéreos, taxistas, hoteles ... pequeños colectivos sociales con gran poder económico ya que controlan sectores estratéticos de la economía... suelen ser un club especial donde es muy dificil o imposible entrar y suelen ser muy pequeños de manera que pasan muy desapercibidos.

Si vamos consintiendo estas situaciones al final lo que tenemos es un sistema económico viciado. Donde pequeños colectivos de gente puede ganar extensas cantidades de dinero sin un trabajo comparable.

Por ejemplo, en Inglaterra un supermercado puede tener una farmacia, pero en España el número de farmacias esta vinculado al número de personas. Al final las personas que despañan los medicamentos son en ambos casos personas con buenos conocimientos pero debido al monopolio en España los precios son mayores.

Lo mismo ocurre con los taxis, en Inglaterra hay taxis y uber en todos sitios y ambos sobreviven y tienen su mercado, sin embargo los taxis en España es otro monopolio. De manera que si voy al aeuropuerto de Alicante a las 12 de la noche y quiero ir a Alicante, tengo que pagar creo recordar que 24 euros, por ese dineral más de uno estaria dispuesto a echar algunas horas para sacarse un dinero, pero en España tiene que ser taxista para poder hacerlo, porque no hay gente con coche que estaria dispuesto a hacerlo.