<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://celisdelafuente.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://celisdelafuente.net/" rel="alternate" type="text/html" /><updated>2026-03-26T22:18:28+00:00</updated><id>https://celisdelafuente.net/feed.xml</id><title type="html">ernesto CELIS DE LA FUENTE</title><subtitle>Software engineer 🧑🏻‍💻 by trade (🐧 Linux rocks!), archery 🏹 and photography 📷 enthusiast, music lover 🪈🎸🎹.
</subtitle><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><entry xml:lang="es"><title type="html">Localstack Intro</title><link href="https://celisdelafuente.net/2022/06/03/LocalStack-Intro.html" rel="alternate" type="text/html" title="Localstack Intro" /><published>2022-06-03T00:00:00+00:00</published><updated>2022-06-03T00:00:00+00:00</updated><id>https://celisdelafuente.net/2022/06/03/LocalStack-Intro</id><content type="html" xml:base="https://celisdelafuente.net/2022/06/03/LocalStack-Intro.html"><![CDATA[<p>LocalStack es un emulador de los servicios de Amazon Web Services que corre en un contenedor Docker en tu sistema local o entorno de CI. LocalStack permite correr AWS Lambda y otros servicios completamente en tu computadora.</p>

<p>Todos los ejemplos a continuación son para sistemas Linux, probado en Ubuntu 20.04 y se asume que <code class="language-plaintext highlighter-rouge">aws-cli</code> está instalado.</p>

<h2 id="instalación">Instalación</h2>

<p>La documentación de LocalStack sugiere como primer método de instalación <code class="language-plaintext highlighter-rouge">localstack-cli</code>. Pero existen alternativas que incluyen Docker, Helm, que pueden funcionar en ambientes de CI y Cockpit, este último ofrece una experiencia de escritorio de acuerdo a la documentación.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 -m pip install --user localstack
</code></pre></div></div>

<p>Terminado el proceso de instalación puedes comprobar que puedas acceder al comando.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>localstack --help
</code></pre></div></div>

<p>Si este no está disponible el <code class="language-plaintext highlighter-rouge">PATH</code> puedes ejecutar como módulo de python.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 -m localstack --help
</code></pre></div></div>

<h2 id="integración-con-aws-cli">Integración con aws-cli</h2>

<p>LocalStack soporta una gama amplia de herramientas para la nube, en la documentación pudes ver la <a href="https://docs.localstack.cloud/integrations/">lista de herramientas oficialmente soportadas</a>.</p>

<p><strong>aws-cli</strong> es la herramienta de línea de comandos que permite interactuar con los servicios de AWS, <strong>awscli-local</strong> es un reemplazo directo que interactua con LocalStack. Desde luego podemos utilizar aws-cli <code class="language-plaintext highlighter-rouge">aws --endpoint-url=http://localhost:4566</code> en lugar de awscli-local, pero yo lo encuentro más comodo.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 -m pip install awscli-local
</code></pre></div></div>

<p>Ahora configurar la herramienta.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aws configure --profile localstack
</code></pre></div></div>

<p>Escribe <code class="language-plaintext highlighter-rouge">test</code> como valor para <strong>AWS Access Key ID</strong> y <strong>AWS Secret Access Key</strong>.</p>

<p>Deja el default <code class="language-plaintext highlighter-rouge">None</code> como valore de <strong>Default region name</strong> y <strong>Default output format</strong>.</p>

<h2 id="inicio-rápido">Inicio rápido</h2>

<p>Ya tienes lo mínimo necesario para empezar a desarrollar en LocalStack. Por ahora una función lambda sencilla servirá, AWS Lambda es uno de los <a href="https://docs.localstack.cloud/aws/feature-coverage/">servicios que LocalStack provee</a>.</p>

<p>Inicia LocalStack, al finalizar  la inicialización debes poder acceder a la URL http://localhost:4566 en tu navegador web.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>localstack start
</code></pre></div></div>

<h3 id="crea-una-función-lambda">Crea una función lambda</h3>

<p>Primero crea el rol de ejecución para la función lambda, IAM es otra de las características de AWS que se emulan en LocalStack.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>awslocal iam create-role --role-name lambda-ex --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
</code></pre></div></div>

<p>Puedes escribir tu propia Lambda para la prueba, pero <a href="https://github.com/ecelis/localstack-posts">aquí</a> hay un repositorio en Github con el código de ejemplo que utilizo en esta publicación.</p>

<p>Clona el rpositorio y crea el archivo <code class="language-plaintext highlighter-rouge">function.zip</code> que vamos a publicar en LocalStack.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/ecelis/localstack-posts.git
cd localstack-posts
zip function.zip index.js
</code></pre></div></div>
<p>Publica la función, el número de cuenta de AWS en el ARN debe ser siempre <code class="language-plaintext highlighter-rouge">000000000000</code> sin especificar región, como en el ejemplo.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>awslocal lambda create-function --function-name my-function \
--zip-file fileb://function.zip --handler index.handler --runtime nodejs12.x \
--role arn:aws:iam::000000000000:role/lambda-ex
</code></pre></div></div>

<p>Terminado el proceso con éxito puedes listar las funciones publicadas en LocalStack.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>awslocal lambda list-functions
</code></pre></div></div>
<p>Invoca la función para tu satisfacción.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>awslocal lambda invoke --function-name my-function out.txt
</code></pre></div></div>

<p>El resultado debe ser un JSON similar al siguiente.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
    "StatusCode": 200,
    "LogResult": "",
    "ExecutedVersion": "$LATEST"
}
</code></pre></div></div>
<p>Usa <code class="language-plaintext highlighter-rouge">cat out.txt</code> para mirar el contenido de <code class="language-plaintext highlighter-rouge">out.txt</code> que debe contener algo similar a los sigiente.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"2022/05/26/[$LATEST]d715a5ed8eddb6f5f731d0ecc584ad8d"
</code></pre></div></div>
<p>LocalStack ofrece una versión <strong>Pro</strong> con más servicios soportados, por ejemplo Lambda Layers o StepFunctions entre <a href="https://docs.localstack.cloud/aws/feature-coverage/">otros</a>.</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><category term="aws" /><category term="localstack" /><category term="español" /><summary type="html"><![CDATA[LocalStack es un emulador de los servicios de Amazon Web Services que corre en un contenedor Docker en tu sistema local o entorno de CI. LocalStack permite correr AWS Lambda y otros servicios completamente en tu computadora.]]></summary></entry><entry xml:lang="en"><title type="html">From docker to podman in less than 10 minutes</title><link href="https://celisdelafuente.net/2020/05/02/From-docker-to-podman-in-less-than-10-minutes.html" rel="alternate" type="text/html" title="From docker to podman in less than 10 minutes" /><published>2020-05-02T00:00:00+00:00</published><updated>2020-05-02T00:00:00+00:00</updated><id>https://celisdelafuente.net/2020/05/02/From-docker-to-podman-in-less-than-10-minutes</id><content type="html" xml:base="https://celisdelafuente.net/2020/05/02/From-docker-to-podman-in-less-than-10-minutes.html"><![CDATA[<p>I switched from Ubuntu to Fedora in my personal laptop a few months ago,
also about the same time I installed Red Hat Enterprise Linux 8 as guest
on Hyper-V for my job.</p>

<p>One of the first things I noticed was the lack of support for Docker and
going full with Kubernetes and OpenShift, which means no real need for
Docker. Currently almost all my work is run in Docker containers,
therefore I was glad to know that Podman is a direct replacement for
Docker.</p>

<p>The Pod Manager tool <code class="language-plaintext highlighter-rouge">podman</code> is a container engine, just like Docker,
but without the requirement of a service daemon running all the time. It
is supported by Red Hat and all the operating system relatives, such as
Fedora and CentOS.  It shares all <code class="language-plaintext highlighter-rouge">docker</code> sub-commands plus a few
others. For more information read the <a href="https://github.com/containers/Demos/tree/master/building/buildah_intro">podman’s manual
pages</a>.</p>

<p><code class="language-plaintext highlighter-rouge">podman</code> talks directly to the image registry, the container and image
storage, and with the Linux kernel through the runC container runtime
process (not a daemon). Podman stores its containers and images in
different places than Docker, each user has its own
<code class="language-plaintext highlighter-rouge">.local/share/containers</code> directory, which allows to several user to use
Podman concurrently. Podman an Docker images are compatible.  Podamn
allows to work with Kubernetes.</p>

<h2 id="how-i-did-it">How I did it?</h2>

<p>Make sure to have the latest updates for your operating system first,
then install <code class="language-plaintext highlighter-rouge">podman</code> which is available by default in Fedora 31 and
later releases.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>dnf update <span class="nt">-y</span>
<span class="nb">sudo </span>dnf <span class="nb">install </span>podman <span class="nt">-y</span>
</code></pre></div></div>

<p>Remove by hand the images you don’t want to migrate, old images,
dangling intermediate build images, test, you know, anything that’s a
waste of storage space. And then iterate through the Docker images and
pull them into Podman.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">for </span>img <span class="k">in</span> <span class="si">$(</span>docker images <span class="nt">--format</span> <span class="s1">'{{.Repository}}:{{.Tag}}'</span><span class="si">)</span><span class="p">;</span> <span class="se">\</span>
<span class="k">do
</span><span class="nb">echo</span> <span class="nv">$img</span><span class="p">;</span> podman pull docker-daemon:<span class="nv">$img</span><span class="p">;</span> <span class="se">\</span>
<span class="k">done</span>

</code></pre></div></div>

<p>Review your images with <code class="language-plaintext highlighter-rouge">podman</code>, just like you’ll do with <code class="language-plaintext highlighter-rouge">docker</code>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>podman images
</code></pre></div></div>

<p>Now you’re ready to get rid of Docker. Stop the daemon, uninstall the
package, delete directories that could use space and drop the <code class="language-plaintext highlighter-rouge">docker</code>
user group.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker system prune <span class="nt">-a</span> <span class="nt">--volumes</span>
<span class="nb">sudo </span>systemctl stop docker
<span class="nb">sudo </span>systemctl disable docker
<span class="nb">sudo </span>dnf remove moby-engine
<span class="nb">sudo rm</span> <span class="nt">-rf</span> /var/lib/docker /var/run/docker
<span class="nb">sudo rm</span> <span class="nt">-rf</span> /etc/docker ~/.docker
<span class="nb">sudo </span>groupdel docker
</code></pre></div></div>

<p>If you’re running CentOS or actual Red Hat Enterprise Linux, the install
steps will change a bit.</p>

<h2 id="now-what">Now what?</h2>

<p>So far I haven’t had major issues using Podman, however there are some
bumps. For example, I use <code class="language-plaintext highlighter-rouge">docker-compose</code> in several projects for
development, I know there is something called <a href=""><code class="language-plaintext highlighter-rouge">podman-compose</code></a>,
which I need to review.</p>

<p>Some CI/CD pipelines in my projects expect the <code class="language-plaintext highlighter-rouge">docker</code> command, I
haven’t make my mind to change that, as I said images are compatible,
but I’d like to use the same tools all along the pipeline, I want to
avoid doing <code class="language-plaintext highlighter-rouge">alias podman=docker</code>.</p>

<p><a href="https://developers.redhat.com/blog/2019/02/21/podman-and-buildah-for-docker-users/">Podman and Buildah for Docker user</a> is a good read for starters.</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><category term="docker" /><category term="podman" /><summary type="html"><![CDATA[I switched from Ubuntu to Fedora in my personal laptop a few months ago, also about the same time I installed Red Hat Enterprise Linux 8 as guest on Hyper-V for my job.]]></summary></entry><entry xml:lang="en"><title type="html">Path to frontend master I</title><link href="https://celisdelafuente.net/2019/10/11/frontend-master-2020-i.html" rel="alternate" type="text/html" title="Path to frontend master I" /><published>2019-10-11T00:00:00+00:00</published><updated>2019-10-11T00:00:00+00:00</updated><id>https://celisdelafuente.net/2019/10/11/frontend-master-2020-i</id><content type="html" xml:base="https://celisdelafuente.net/2019/10/11/frontend-master-2020-i.html"><![CDATA[<h4 id="20221127-update">2022/11/27 UPDATE</h4>

<ul>
  <li>Text review, changes in react app to fix errors</li>
  <li>I don’t have and OpenFaaS deploment anymore, so the back was moved to something else.</li>
  <li>The source code for the new thing included in the new <a href="https://codesandbox.io/s/github/ecelis/avocado">codesanbox repo</a>.</li>
</ul>

<hr />

<p>I decided to start a series of front end projects that I found at
DEV.to “<a href="https://dev.to/simonholdorf/9-projects-you-can-do-to-become-a-frontend-master-in-2020-n2h">9 Projects you can do to become a frontend Master in
2020</a>”.
This post is about my own spin-off from the first project listed in that
post by Simon Holdorf, a movie search app
using React with hooks only, avoiding Class based components.</p>

<p>The fact that the challenge involves using the new hooks feature in
React interests me particularly, because I recently revisited React
after I learnt it one year and a half ago, then I left front end
completely all this time. The base for my spin off comes from Samuel
Omole’s <a href="https://www.freecodecamp.org/news/how-to-build-a-movie-search-app-using-react-hooks-24eb72ddfaf7/">tutorial</a>
at freecodecamp.org</p>

<p>The <code class="language-plaintext highlighter-rouge">Header</code> and <code class="language-plaintext highlighter-rouge">Movie</code> components are almost identical to the ones
Samuel wrote, but I took a few liberties in the <code class="language-plaintext highlighter-rouge">Search</code> and <code class="language-plaintext highlighter-rouge">App</code>
components. Also I prefer <code class="language-plaintext highlighter-rouge">.jsx</code> extensions for components and <code class="language-plaintext highlighter-rouge">.js</code> for
plain old javascript code. However I encourage you to read his tutorial
because he goes deeper in the logic behind the app and explains how the
hooks work, it is not my goal to repeat him.</p>

<p>What I do different?</p>
<ul>
  <li>OMDB API key is not exposed in the React app</li>
  <li>A <del><a href="https://www.openfaas.com/">OpenFaaS</a></del> server-less function acts as proxy to OMDB</li>
  <li>keywords for narrowing the search and limiting number of results:
    <ul>
      <li>title:<em>“movie title”</em></li>
      <li>type:<em>movie, series, episode</em></li>
      <li>limit:<em>12</em></li>
    </ul>
  </li>
</ul>

<p><a href="https://create-react-app.dev/">create-react-app</a> is the tool I am more
used to bootstrap React projects, honestly I haven’t tried many others
besides Gatsby. I became a patron at
<a href="https://codesandbox.io">CodeSandbox</a> so why not use it for this
project?  The <code class="language-plaintext highlighter-rouge">codesandbox</code> cli made a breeze to export the project I
had already bootstrapped from my laptop to the web editor. You can also
bootstrap your project directly in CodeSandbox and then export to a
Github repository and or publish it to Netlify. Go and check them out!</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nb">install</span> <span class="nt">-g</span> codesandbox
codesandbox ./
</code></pre></div></div>

<p>Move <code class="language-plaintext highlighter-rouge">App.js</code> and <code class="language-plaintext highlighter-rouge">App.css</code> to <code class="language-plaintext highlighter-rouge">components/App.js</code>.</p>

<p>Add <code class="language-plaintext highlighter-rouge">components/Header.jsx</code>.</p>

<iframe src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&amp;fontsize=14&amp;module=%2Fsrc%2Fcomponents%2FHeader.jsx&amp;view=editor" title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

<p>Also add a <code class="language-plaintext highlighter-rouge">components/Movie.jsx</code> file:</p>

<iframe src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&amp;fontsize=14&amp;module=%2Fsrc%2Fcomponents%2FMovie.jsx&amp;view=editor" title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

<p>The next component <code class="language-plaintext highlighter-rouge">components/Search.jsx</code> will introduce <strong>hooks</strong>, the
new React feature that allow to handle state in functional components. I
really do not like the idea of classes in JavaScript and since I am not
a long time React developer I very much welcome hooks.</p>

<iframe src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&amp;fontsize=14&amp;module=%2Fsrc%2Fcomponents%2FSearch.jsx&amp;view=editor" title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

<p>In the Search component the <code class="language-plaintext highlighter-rouge">useState</code> hook takes the initial state as
parameter and returns an array with the current state (similiar to
<code class="language-plaintext highlighter-rouge">this.state</code> but does not merge old and new states togheter) and a
function to update the state <code class="language-plaintext highlighter-rouge">setSearchValue</code> in this case, which is the
same as <code class="language-plaintext highlighter-rouge">this.setState</code>.</p>

<p><code class="language-plaintext highlighter-rouge">useEffect</code> is a hook which allows to perform <em>side effects</em> in your
components, like fetching data from OMDB in this app. Other hook is
<code class="language-plaintext highlighter-rouge">useReducer</code> which works similar to redux reducers, it accepts state and
action and returns the current state and a dispatch method.</p>

<iframe src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&amp;fontsize=14&amp;module=%2Fsrc%2Fcomponents%2FApp.jsx&amp;view=editor" title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

<p>There are a couple of unbreakable rules for using hooks in React:</p>

<ul>
  <li><strong>Only call hooks at the top level of function components.</strong></li>
  <li><strong>Do not call hooks inside loops, conditions or nested functions.</strong></li>
  <li><strong>Only call hooks from React function components</strong>.</li>
  <li><strong>Do not call hooks from regular JavaScript functions.</strong></li>
</ul>

<p>You can read more about <a href="https://reactjs.org/docs/hooks-intro.html">Hooks</a> in the React docs.</p>

<p>In summary, I will be using hooks over class based components in my
current and next React projects, a good thing is that class and function
components with hooks mix well, so no heavy refactoring of
class components and slow adoption of hooks is a good approach for
existing projects.</p>

<p>You can try and explore the <a href="https://github.com/ecelis/avocado">code for the working movie app</a>. Be ware!
Since this is a demo the server-less function behind is not setup to
scale and a heavy load of requests may take it down temporarily.</p>

<iframe src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&amp;fontsize=14&amp;module=%2Fsrc%2Fcomponents%2FApp.jsx" title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals
allow-forms allow-popups allow-scripts allow-same-origin"></iframe>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><category term="javascript" /><category term="react" /><summary type="html"><![CDATA[2022/11/27 UPDATE]]></summary></entry><entry><title type="html">JavaScript notes I</title><link href="https://celisdelafuente.net/2019/03/21/javascript-notes-i.html" rel="alternate" type="text/html" title="JavaScript notes I" /><published>2019-03-21T00:00:00+00:00</published><updated>2019-03-21T00:00:00+00:00</updated><id>https://celisdelafuente.net/2019/03/21/javascript-notes-i</id><content type="html" xml:base="https://celisdelafuente.net/2019/03/21/javascript-notes-i.html"><![CDATA[<p>Let’s review  some JavaScript features in a hurry!</p>

<h2 id="iterables">Iterables</h2>

<p>Objects that can be used in <code class="language-plaintext highlighter-rouge">for..of</code> are called iterable.</p>

<p>Iterables must implement the method named <code class="language-plaintext highlighter-rouge">Symbol.iterator</code>. The result
of <code class="language-plaintext highlighter-rouge">obj[Symbol.iterator]</code> is called an iterator.  An iterator must have
the method named <code class="language-plaintext highlighter-rouge">next()</code> that returns an object <code class="language-plaintext highlighter-rouge">{done: Boolean, value:
any}</code>, the value is the next value.  The <code class="language-plaintext highlighter-rouge">Symbol.iterator</code> method is
called automatically by <code class="language-plaintext highlighter-rouge">for..of</code>, but we also can do it directly.</p>

<p><code class="language-plaintext highlighter-rouge">Array.from(obj[, mapFn, thisArg])</code> makes a real Array of an iterable or
array-like obj, and we can then use array methods on it. The optional
arguments mapFn and thisArg allow us to apply a function to each item.</p>

<h2 id="destructuring">Destructuring</h2>

<p>Map an object or array to variables.</p>

<p>Object syntax:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let {prop : varName = default, ...} = object
</code></pre></div></div>

<p>Array syntax:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let [item1 = default, item2, ...rest] = array
</code></pre></div></div>

<p>The first item goes to <code class="language-plaintext highlighter-rouge">item1</code>; the second goes into <code class="language-plaintext highlighter-rouge">item2</code>, all the rest
makes the array rest.</p>

<h2 id="map-and-set">Map and Set</h2>

<p><code class="language-plaintext highlighter-rouge">Map</code>, is a collection of keyed values, it allows objects to be keys and
provides a <code class="language-plaintext highlighter-rouge">size</code> property.</p>

<p><code class="language-plaintext highlighter-rouge">Set</code>, is a collection of unique values, does not allow to reorder elements.</p>

<p>The following allow garbage-collection:
There ara also <code class="language-plaintext highlighter-rouge">WeakMap</code> and <code class="language-plaintext highlighter-rouge">WeakSet</code> which provide garbage collection,
I need to research more about these. Maybe the next post.</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><category term="javascript" /><summary type="html"><![CDATA[Let’s review some JavaScript features in a hurry!]]></summary></entry><entry><title type="html">Linux Kernel Notes I</title><link href="https://celisdelafuente.net/2015/06/26/linux-kernel-notes-i.html" rel="alternate" type="text/html" title="Linux Kernel Notes I" /><published>2015-06-26T00:00:00+00:00</published><updated>2015-06-26T00:00:00+00:00</updated><id>https://celisdelafuente.net/2015/06/26/linux-kernel-notes-i</id><content type="html" xml:base="https://celisdelafuente.net/2015/06/26/linux-kernel-notes-i.html"><![CDATA[<p>Notes and bookmarks I’ve gathered by doing the <a href="http://eudyptula-challenge.org/">Eyduptula
challenge</a></p>

<h2 id="must-read">Must read</h2>

<ul>
  <li><a href="http://tldp.org/HOWTO/Module-HOWTO/">Linux Loadable Kernel Module
HOWTO</a></li>
  <li><a href="http://kernelnewbies.org/KernelBuild">Linux Kernel Newbies -
KernelBuild</a></li>
  <li>Documentation/SubmittingPatches in the Linux source tree</li>
  <li>Documentation/CodingStyle</li>
  <li>Documentation/email-clients.txt</li>
</ul>

<p>Grab yourself a copy of the mainline kernel repository</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
</code></pre></div></div>

<h2 id="build-steps">Build steps</h2>

<p><em>.config</em> CONFIG_LOCALVERSION_AUTO=y</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make localmodconfig
make silentoldconfig
make menuconfig
make -j4 all
make modules_install
make install
</code></pre></div></div>

<h2 id="make-a-patch">Make a patch</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SRCTREE= linux
MYFILE= drivers/net/mydriver.c
cp $MYFILE $MYFILE.orig
vi $MYFILE # make your change
cd ..
diff -up $SRCTREE/$MYFILE{.orig,} &gt; /tmp/patch
</code></pre></div></div>

<p>Multiple files</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MYSRC= /dev/linux
tar xvzf linux-3.19.tar.gz
mv linux-3.19 linux-3.19-vanilla
diff -uprN linux-3.19-vanilla/Documentation/dontdiff \
  linux-3.19-vanilla $MYSRC &gt; /tmp/patch
</code></pre></div></div>

<p>Check your patches with the patch style checker <code class="language-plaintext highlighter-rouge">scripts/checkpatch.pl</code></p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><category term="linux" /><summary type="html"><![CDATA[Notes and bookmarks I’ve gathered by doing the Eyduptula challenge]]></summary></entry><entry><title type="html">Introduction to R Data types</title><link href="https://celisdelafuente.net/2015/06/12/Introduction-to-R-data-types.html" rel="alternate" type="text/html" title="Introduction to R Data types" /><published>2015-06-12T00:00:00+00:00</published><updated>2015-06-12T00:00:00+00:00</updated><id>https://celisdelafuente.net/2015/06/12/Introduction-to-R-data-types</id><content type="html" xml:base="https://celisdelafuente.net/2015/06/12/Introduction-to-R-data-types.html"><![CDATA[<p>Everything in R is an object, there are five basic or <em>“atomic”</em> classes
of objects. The most basic object is a <strong>vector</strong>, it can contain
objects of the same class only, the one exception is a <strong>list</strong>, which
is represented as a vector but can contain different classes and indeed
that’s usually how lists are used.</p>

<h2 id="objects">Objects</h2>

<ul>
  <li>character</li>
  <li>numeric (real numbers)</li>
  <li>integer</li>
  <li>complex (3 - 4i)</li>
  <li>logical (True/False)</li>
</ul>

<p>Numbers are double precision real numbers. If needed to specify an
integer we should use the <strong>L</strong> suffix. There are a couple of special
numbers, <strong>Inf</strong> and <strong>NaN</strong> which stand for Infinite and Not A Number.</p>

<p>Objects in R can have attributes</p>

<ul>
  <li>name, dimnames</li>
  <li>dimensions (matrices, arrays)</li>
  <li>class</li>
</ul>

<h2 id="vectors">Vectors</h2>

<p>The <code class="language-plaintext highlighter-rouge">c()</code> function is used to create vectors.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- c(1, 3, 4, 7)
x &lt;- vector("numeric", lenght=2)
</code></pre></div></div>

<p>When different objects are mixed in a vector, <em>coercion</em> occurs so that
every element in the vector is of the same class. Objects can be
explicitly coerced using the <code class="language-plaintext highlighter-rouge">as.*</code> function. If non-sense coercion is
tried the result is <strong>NA</strong>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- 0:6
class(x)
as.numeric(x)
as.logical(x)
as.character(x)
</code></pre></div></div>

<h2 id="lists">Lists</h2>

<p>Lists are very important in R, the element in a list are enclosed in
double square brackets and can be accesed by their index in the list.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- list(1, "a", TRUE)
[[2]]
[2] "a"
</code></pre></div></div>

<h2 id="matrices">Matrices</h2>

<p>Special vetor in R with a <em>dimension attribute</em> which is itself an
integer vector of lenght 2 <em>(nrow, ncol)</em>. Matrices are constructed
column-wise.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>m &lt;- matrix(nrow = 2, ncol = 3)
dim(m)
attributes(m)
</code></pre></div></div>

<p>Matrices can also be created directly from vectors by adding a dimension
attribute.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>m &lt;- 1:10
dim(m) &lt;- c(2,5)
</code></pre></div></div>

<p>Binding can be used to create matrices also by using the functions
<code class="language-plaintext highlighter-rouge">cbind()</code> and <code class="language-plaintext highlighter-rouge">rbind()</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- 1:3
y &lt;- 10:12
cbind(x,y)
rbind(x,y)
</code></pre></div></div>

<h2 id="factors">Factors</h2>

<p>Are used to represent categorical data, can be ordered or unordered. One
can think a factor as an integer vector where each integer has a
<em>label</em>. Using factors with labels is better than using integers because
factors al self-described.</p>

<p>The order of the labels can be set using the <strong>levels</strong> argument, this
can be important for linear modeling.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- factor(c("yes", "yes", "no", "yes", "no"), levels = c("yes", "no"))
table(x)
unclass(x)
attr(,"levels")
</code></pre></div></div>

<h2 id="missing-values">Missing values</h2>

<p>Missing values are denoted by <strong>NA</strong> or <strong>NaN</strong> fr undefined
mathematical operations. NA values can have a class also, so there are
integer NA, character NA, etc. A NaN value is also an NA value, but not
the opposite.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- c(1, 2, NA, 10, 3)
is.na(x)
is.nan(x)
</code></pre></div></div>

<h2 id="data-frames">Data frames</h2>

<p>Are used to store tabular data, they are represented as a special list
has to have the same length. Each element can be thought of as a column
and the length of each element of the list is the number of rows. Unlike
matrices, data frames can store different classes of objects in each
column. Data frames have a special attribute called <em>row.names</em></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- data.frame(foo = 1:4, bar = c(T, T, F, F))
x
nrow(x)
ncol(x)
</code></pre></div></div>

<h2 id="names">Names</h2>

<p>R objects can have names, which is useful for writing readable code.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x &lt;- 1:3
names(x)
x
names(x) &lt;- c("foo", "bar", "norf")
x
x &lt;- list(a = 1, b = 2, c = 3)
x
m &lt;- matrix(1:4, nrow = 2, ncol = 2)
dimnames(m) &lt;- list(c("a", "b"), c("c", "d"))
m
</code></pre></div></div>

<p>EOF</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><summary type="html"><![CDATA[Everything in R is an object, there are five basic or “atomic” classes of objects. The most basic object is a vector, it can contain objects of the same class only, the one exception is a list, which is represented as a vector but can contain different classes and indeed that’s usually how lists are used.]]></summary></entry><entry><title type="html">GNU Guix Hackathon-09-2014</title><link href="https://celisdelafuente.net/2014/09/29/gnu-guix-hackathon-09-2014.html" rel="alternate" type="text/html" title="GNU Guix Hackathon-09-2014" /><published>2014-09-29T00:00:00+00:00</published><updated>2014-09-29T00:00:00+00:00</updated><id>https://celisdelafuente.net/2014/09/29/gnu-guix-hackathon-09-2014</id><content type="html" xml:base="https://celisdelafuente.net/2014/09/29/gnu-guix-hackathon-09-2014.html"><![CDATA[<p>In the weekend of September 27th &amp; 28th and to celebrate the 30th
anniversary of GNU an on line hackathon of GNU Guix was held. Although I
didn’t officially joined, I took the chance to try Guix for the first
time.</p>

<p>There are two ways of currently running GNU Guix, either it could be
installed on top of an existing GNU/Linux distribution, or installed
directly on bare metal (or a virtual machine for the instance). Since
the virtualization platform I use is VirtualBox, this was my primary
target, in contrast qemu is the preferred choice of Guix developers,
because its GPL license I assume.</p>

<p>Being in alpha state, the GNU Guix distribution provides a very basic
USB image to boot and install the system, VirtualBox currently does not
boot from USB, so I had to convert the installer raw image to some
format which VirtualBox could handle. I tried VBoxManage at first, but
it didn’t work or maybe I was unable to figure out how to do so, in the
end I used qemu-img command to achieve the task.</p>

<p>In Gitorious you can find my <a href="https://gitorious.org/ecelis-guix/hackathon">notes and some
guides</a> which I wrote
during this two days of the hackathon.</p>

<p>The latest GNU Guix installer image version available for download is
Guix-0.7 which is flawed, <code class="language-plaintext highlighter-rouge">guix --version</code> shows the right version but
the bundled packages are from Guix-0.6. It is not a showstopper, since
you can easily upgrade to the latest version right before installing to
your hard drive. This little bug slowed my install a few hours until I
found the solution when someone else hit the same problem in #guix at
freenode.net</p>

<p>The installer script is rather basic, do not expect anything fancy like
hard disk re-partitioning, much less a GUI. It does not mean that it is
hard to install, any mididly experienced unix user should be able to use
fdisk, e2label, mount, sed and other basic commands to get a running GNU
Guix system. One thing I missed though was the lack of vi or ed text
editors, my keyboard is broken and keys ‘Z’ and left ‘CTRL’ don’t work.
VirtualBox grabs hold of the right ‘CTRL’ for its own purposes and the
only two editors available in the installer image are nano and zile (an
Emacs clone), both unusable with my current keyboard.</p>

<p>Also the installer fetches pre-built binaries from hydra.gnu.org,
sometimes this hosts is overloaded or simply unresponsive and you will
get this <em>“guix-system: error: build failed: unexpceted-end-of-file”</em>
message instead of the cool one <em>“Installation finished. No error
reported”</em>, just re-run the last command until the task finishes
successfully. If everything went well, now you should have a shiny new
GNU Guix system ready to be booted into.</p>

<p>EOF</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><summary type="html"><![CDATA[In the weekend of September 27th &amp; 28th and to celebrate the 30th anniversary of GNU an on line hackathon of GNU Guix was held. Although I didn’t officially joined, I took the chance to try Guix for the first time.]]></summary></entry><entry><title type="html">SlackwareARM in Cubieboard2</title><link href="https://celisdelafuente.net/2014/07/09/slackwarearm-in-cubieboard2.html" rel="alternate" type="text/html" title="SlackwareARM in Cubieboard2" /><published>2014-07-09T00:00:00+00:00</published><updated>2014-07-09T00:00:00+00:00</updated><id>https://celisdelafuente.net/2014/07/09/slackwarearm-in-cubieboard2</id><content type="html" xml:base="https://celisdelafuente.net/2014/07/09/slackwarearm-in-cubieboard2.html"><![CDATA[<p>From early this year I’ve been playing with an Allwiner SoC, the
Cubieboard2 is a System on a Chip with 1GHz dual core CPU, 1GB RAM, 4GB
NAND, 1 100MB Ethernet port, MicroSD card slot and a bunch of other
niceties, expansion ports and what not. It comes preloaded with Android
Jelly Bean, but there are several GNU/Linux flavors available.</p>

<p>Sadly I ain’t very fond of none of the available distros, and Slackware
has an ARM port which is now officialy endorsed by Patrick Volkerdi
himself. So I decided to give it a try.</p>

<p>SlackwareARM has official support for some boards and community support
for some others, the main difference is that the official ones work with
the standard Slackware installer and the ones supported by the community
don’t. Luckly the SlackwareARM team provides a compressed mini-root
filesystem with the bare minimal to bootstrap the system.</p>

<p>Here I’ll give only an overview of the steps needed to bootstrap
SlackwareARM 14.1 on Cubieboard2. Detailed guidelines are available in
Spanish language in <a href="https://freeshell.de/~ecelis/doku.php?id=cubieboard2">Mi
Kiwi</a>.</p>

<p>All my hardware runs some sort of Unix like operating system, everything
I describe here was done in a laptop running Slackware64 14.1 with
multi-lib enabled.</p>

<ol>
  <li>You need to get a miniroot file from
<a href="http://ftp.arm.slackware.com/slackwarearm/slackwarearm-devtools/minirootfs/roots/">here</a>
and unpackit somewhere.</li>
  <li>You’ll also need the
<a href="https://github.com/linux-sunxi/u-boot-sunxi.git">u-boot-sunxi</a>,
<a href="https://github.com/linux-sunxi/sunxi-tools.git">sunxi-tools</a>,
<a href="https://github.com/linux-sunxi/sunxi-boards.git">sunxi-boards</a> and
<a href="https://github.com/linux-sunxi/linux-sunxi.git">linux-sunxi</a> git cloned
repositories.</li>
  <li>Finally a cross toolchain to build the sources, get one from
<a href="http://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-gnueabi/">here</a>.
I did choose the arm-2012-03-57-arm-none-linux-gnueabi.</li>
  <li>Build the sunxi-tools, u-boot-sunxi and linux-sunxi</li>
  <li>Copy the <code class="language-plaintext highlighter-rouge">u-boot-with-spl.bin</code> to the mSD</li>
  <li>Then copy the resulting <code class="language-plaintext highlighter-rouge">uImage</code> kernel and install <code class="language-plaintext highlighter-rouge">modules</code> into
the rootfs directory.</li>
  <li>Edit and compile the <code class="language-plaintext highlighter-rouge">Cubieboard2.fex</code> into the <code class="language-plaintext highlighter-rouge">script.bin</code> file</li>
  <li>Edit the <code class="language-plaintext highlighter-rouge">uEnv.txt</code> file</li>
  <li>Edit and compile the <code class="language-plaintext highlighter-rouge">boot.cmd</code> into boot.scr</li>
  <li>Edit <code class="language-plaintext highlighter-rouge">rootfs/etc/fstab</code></li>
</ol>

<p>Place the mSD card into the Cubieboard2 and boot it, if you have an USB
Serial converter you can watch/debug the boot and load of the kernel
attaching your terminal to the serial console using either, <code class="language-plaintext highlighter-rouge">cu</code>, <code class="language-plaintext highlighter-rouge">minicom</code>
or <code class="language-plaintext highlighter-rouge">screen</code>.</p>

<p>For the lazy bums out there, you can download either, a mSD card image
file ready to boot, or the root filesystem compressed and the
u-boot-with-spl.bin files to customize your install from
<a href="http://www.mediafire.com/?gj4k5mvneq7mn">MediaFire</a>.</p>

<p>EOF</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><summary type="html"><![CDATA[From early this year I’ve been playing with an Allwiner SoC, the Cubieboard2 is a System on a Chip with 1GHz dual core CPU, 1GB RAM, 4GB NAND, 1 100MB Ethernet port, MicroSD card slot and a bunch of other niceties, expansion ports and what not. It comes preloaded with Android Jelly Bean, but there are several GNU/Linux flavors available.]]></summary></entry><entry><title type="html">Surveillance, people and power</title><link href="https://celisdelafuente.net/2014/02/12/surveillance-people-and-power.html" rel="alternate" type="text/html" title="Surveillance, people and power" /><published>2014-02-12T00:00:00+00:00</published><updated>2014-02-12T00:00:00+00:00</updated><id>https://celisdelafuente.net/2014/02/12/surveillance-people-and-power</id><content type="html" xml:base="https://celisdelafuente.net/2014/02/12/surveillance-people-and-power.html"><![CDATA[<p>I just twitted about “<a href="https://thedaywefightback.org/international/">The Day We Fight
Back</a>” a movement
sponsored for some organizations like the <a href="http://www.fsf.org/">Free Software
Foundation</a>, the <a href="https://www.eff.org/">Electronic Frontier
Foundation</a>, among other tech-related bodies and
associations. Put aside the time (a decade at least) being known for my
support to the free software and also open source software, which
prompted me to start typing this post is the kind of job I’m doing
nowadays.</p>

<p>Going straight to the point, directly under my control are around 10
cameras installed abroad the city where I currently live. This is not
the first time I do security related development. And for the most part
(thinking as an ex-volunteer firefighter) I really think that the
current project which involves more than cameras is really helpful for
the people in this city. Let’s temporarily forget the goal of the
project.</p>

<p>I think about the cameras as the eyes of first response corps, certainly
these days (almost) everyone carries a mobile phone capable of doing
free calls to the emergency number, a big chunk of this mobile users own
a so called smart-phone capable not only of making the emergency call,
but also most of these gadgets are equipped with sensors and in some
cases software capable of sending geo-location data and media to the
emergency control centres. What this devices can’t provide neither
replace is the training of first responders teams and dispatch
operators.</p>

<p>So, the right mix of technology with trained and highly ethic people in
charge of the cameras I was talking about in the first place, make the
surveillance projects worth. The problem arises from an education and
economics background. I can sleep fine every night, since I do a
professional and transparent (to maximum allowed extent) work, I was
grown educated by certain ethics and in a relatively comfortable
environment. Speaking of my current work, all code I’ve written is being
published with some sort of free or open source licence, so it can be
openly audited. But what about the high rank officers, middle ground
operators and other people with access to the technology and who are
able to exploit it for their own purposes?</p>

<p>Technically, I or any person with the right skill set can create things
that can be twisted into evil tools by other kind of skilled people, how
do you control the later?</p>

<p>I could stop doing what I do, but some one else will do it anyways. The
key is education which is the easiest part, since the other part, the
economics are a bit more complicated to even think about, but easily
controlled by education means though.</p>

<p>EOF</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><summary type="html"><![CDATA[I just twitted about “The Day We Fight Back” a movement sponsored for some organizations like the Free Software Foundation, the Electronic Frontier Foundation, among other tech-related bodies and associations. Put aside the time (a decade at least) being known for my support to the free software and also open source software, which prompted me to start typing this post is the kind of job I’m doing nowadays.]]></summary></entry><entry><title type="html">Ten years of a great learning experience</title><link href="https://celisdelafuente.net/2013/12/10/ten-years-of-great-learning-experience.html" rel="alternate" type="text/html" title="Ten years of a great learning experience" /><published>2013-12-10T00:00:00+00:00</published><updated>2013-12-10T00:00:00+00:00</updated><id>https://celisdelafuente.net/2013/12/10/ten-years-of-great-learning-experience</id><content type="html" xml:base="https://celisdelafuente.net/2013/12/10/ten-years-of-great-learning-experience.html"><![CDATA[<p>In 2003 I started seriously playing with the GNU/Linux operating system,
it was a matter of months to make the switch from Windows XP to almost
running Slackware 9.1 only. That choice was a good one, it brought along
a learning tidal that I’ve been enjoying since then.</p>

<p>One year or so passed and in July of 2004 I already felt very
comfortable working in the shell, coding in Emacs and even playing my
mp3 music collection and DVDs, things weren’t so smooth and fancy as
today, there wasn’t transparent borders, or shadows, Ubuntu was in
diapers and setting up the graphic desktop was a pain in the ass in your
lucky day. But I learnt a lot about my hardware and the inner workings
of the operating systems, not only Linux based ones.</p>

<p>I got an old IBM Pentium 100MHz with 48MB RAM and 20G Hard Drive along
with an USRobotics 56k modem, the modem was intended to provide Internet
connectivity for my main PC that ran Slackware, the internal modem of
the later didn’t played well with Linux. Thinking about what to do with
the Pentium machine I stumbled upon some on-line article about Hotmail.
I thought of learning about servers by running my own web, email, ftp
and any kind of server on the venerable IBM hardware, which proved to be
a fine workhorse running by several months almost unatended with no
downtime (actually the server ran several years, but I upgraded the
hardware very soon), unless lack of power of the like. I wasn’t bound to
dialup too much time, very soon in mid 2004 I leased a 256Kbps DSL
connection which made perfect fit with the server project.</p>

<p>I started researching about pre-Microsoft, Hotmail’s original
infrastructure, trying to emulate it if possible, it turned out that
FreeBSD was the operating system used by Hotmail and qmail was the MTA.
I already knew about the BSD family of unices, but never touched one of
such beasts before. Again the task of learning was daunting at times,
but very joyful overall. This time gained a lot of knowledge about the
workings of the Internet, web servers and the way http
requests/responses are handled (really helpful for my career as web apps
developer), qmail and how the protocols SMTP, IMAP and POP work
togheter, I used to host my own domain, both web and email and my own
Subversion server. FreeBSD 4.1 was the operating system choice, also
great for learning about true unix which is not the same as GNU/Linux.</p>

<p>In ten years I’ve seen the raise (meaning widespread use) of
virtualization technologies which I started using in 2005 with Xen and
VMware, later clouds came and I was also interested in learning about
it, good old cfe.homeunix.org (which was the domain name of my server)
then left the physical layer and went to heaven, well only to the cloud
in the form of an AWS AMI.</p>

<p>And the learning path does not seem to end soon, today I got <a href="http://ipv6.esblender.org/">my first
server on IPv6</a> (you need to be on IPv6 in
order to be able to reach the website). Thanks to Hurricane Electric and
their <a href="https://tunnelbroker.net/">IPv6 Tunnelbroker</a> service, I know a
bit about IPv6 (I should know, I did the CCNA course) and the difference
between v4 and v6 is more than 2 :-)</p>

<p>EOF</p>]]></content><author><name>Ernesto Celis</name><email>me@celisdelafuente.net</email></author><summary type="html"><![CDATA[In 2003 I started seriously playing with the GNU/Linux operating system, it was a matter of months to make the switch from Windows XP to almost running Slackware 9.1 only. That choice was a good one, it brought along a learning tidal that I’ve been enjoying since then.]]></summary></entry></feed>