samedi 7 septembre 2013

Ansible: l'orchestration facile (2/2)


Cet article est la suite de l'article n°1 présentant Ansible. Celui-ci a pour but de créer notre premier playbook.

En route !

Mon premier Playbook

Objectifs


Maintenant que l'on dispose de notre structure de base, on va configurer la liste des tâches permettant d'installer Tomcat8 sur un Ubuntu 12.04 à savoir:

  1. Installer le paquet OpenJDK 7 (le paquet se nomme openjdk-7-jdk)
  2. Créer un dossier permettant le téléchargement de l'archive de tomcat8 (dans /home/vagrant/archives)
  3. Télécharger tomcat8 depuis le miroir suivant
  4. Créer le dossier /opt/apache-tomcat appartenant à l'utilisateur vagrant
  5. Décompresser notre archive
  6. Créer un lien symbolique de /opt/apache-tomcat/apache-tomcat-8.0.0-RC1 à /opt/apache-tomcat/tomcat8
  7. Modifier le fichier server.xml
  8. Redémarrer tomcat à chaque fois que le fichier catalina.properties est modifié

Résolution

Étape 1: installer un paquet

 

On va créer une tâche permettant l'installation d'un paquet sur notre Ubuntu dans le fichier roles/tomcat8/tasks/main.yml:

- name: install package openJDK 7
  apt: pkg=openjdk-7-jdk update_cache=yes
  sudo: yes

Toutes les tâches nécessitent un nom qui sera affiché lors de l'exécution d'Ansible.
La deuxième ligne précise le module a utiliser à savoir ici le module "apt", on lui passe deux paramètres pkg (qui indique le nom du paquet à installer) et update_cache (qui va déclencher un apt-get update avant l'installation). Mais il existe d'autres options.
Enfin la dernière ligne indique qu'il faut lancer cette commande via sudo.

Testons maintenant notre première tâche via la commande suivante qui va exécuter notre playbook site.yml sur l'ensemble des machines de notre fichier production:

$ ansible-playbook -i production site.yml

Et le résultat (ça peut prendre un peu de temps):
PLAY [application-server] ***************************************************** 
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [install package openJDK 7] *********************************************
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
Si vous avez des vaches qui s'affichent vous pouvez soit désinstaller le paquer cowsay soit exécuter la commande suivante:
export ANSIBLE_NOCOWS=1

Étape 2: créer un dossier

 

Pour créer un dossier on ajoute juste une tâche à notre fichier main.yml en utilisant le module file:
- name: create archives folder
  file: path=/home/vagrant/archives state=directory
On teste à nouveau et voilà le résultat:
PLAY [application-server] ***************************************************** 
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [install package openJDK 7] *********************************************
ok: [127.0.0.1]
TASK: [create archives folder] ************************************************
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=3 changed=1 unreachable=0 failed=0
On peut voir ici qu'Ansible ne ré-installe pas le package openJDK (statut: ok) mais créé par contre bien notre dossier (statut: changed).

Pour les étapes suivantes je vais vous laisser travailler en ne vous donnant que le nom des modules à utiliser. Le fichier final main est indiqué à la fin de l'article.

Étape 3: télécharger une archive

 

Utiliser pour cela le module get_url.

Étape 4: créer un dossier

 

Voir l'étape 2 en ajoutant les options qui vont bien.

Étape 5: décompresser une archive

 

Utiliser pour cela le module command. Attention à bien utiliser l'option creates pour ne pas décompresser l'archive à chaque exécution d'Ansible.

Étape 6: créer un lien symbolique

 

Encore et toujours le module file avec les options dest et src ce coup-ci.

Étape 7: Modifier le fichier server.xml

 

Pour copier un fichier depuis notre dossier roles/tomcat8/files il suffit d'utiliser le module copy. Pour l'exemple le fichier local copié sur le serveur distant est le fichier server.xml classique auquel ont été enlevé les commentaires:

- name: Copy server.xml
  copy: dest=/opt/apache-tomcat/tomcat8/conf/server.xml owner=vagrant group=vagrant src=roles/tomcat8/files/server.xml

Étape 8: Redémarrer automatiquement Tomcat

 

L'étape précédente nous a permis de modifier facilement la configuration de nos serveurs Tomcat. Néanmoins il faut après une modification de la conf redémarrer le serveur.
Pour réaliser cela nous allons ajouter un handler, une action qui ne sera exécutée que sur notification d'une autre action. Ainsi si le fichier de conf n'est pas modifié Tomcat ne sera pas redémarré.
On ajoute une ligne à notre tâche de l'étape 7 pour notifier notre handler:

- name: Copy server.xml
  copy: dest=/opt/apache-tomcat/tomcat8/conf/server.xml owner=vagrant group=vagrant src=roles/tomcat8/files/server.xml
  notify: restart tomcat
Et on créé le fichier handler correspondant dans roles/tomcat8/handlers/main.yml:

- name: restart tomcat
  shell: /opt/apache-tomcat/tomcat8/bin/shutdown.sh && /opt/apache-tomcat/tomcat8/bin/startup.sh
Voilà normalement lors de la prochaine modification du fichier server.xml notre tomcat sera redémarré. Pour tester nous pouvons rajouter une ligne vide dans le fichier roles/tomcat8/files/server.xml et relancer ansible-playbook:

PLAY [application-server] ***************************************************** 
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [install package openJDK 7] *********************************************
ok: [127.0.0.1]
TASK: [create archives folder] ************************************************
ok: [127.0.0.1]
TASK: [Download Tomcat 8] *****************************************************
ok: [127.0.0.1]
TASK: [Create tomcat directory] ***********************************************
ok: [127.0.0.1]
TASK: [Unzip tomcat] **********************************************************
skipping: [127.0.0.1]
TASK: [Create Tomcat symlink] *************************************************
ok: [127.0.0.1]
TASK: [Copy server.xml] *******************************************************
changed: [127.0.0.1]
NOTIFIED: [restart tomcat] ****************************************************
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=8 changed=2 unreachable=0 failed=0

Fichier Final

 

Aller plus loin

Il est possible de faire encore plus de chose avec Ansible comme par exemple :

Bref aller jeter un oeil à la doc qui bien qu'un peu fouillis contient l'essentiel.


Post 14/52

vendredi 6 septembre 2013

Ansible : l'orchestration facile



L'une des choses qui m'intéresse énormément ces dernières années est le déploiement automatisé et industrialisé des plateformes en particulier via Puppet. Marre des scripts shell !

Présentation

Aujourd'hui j'ai découvert un outil nommé Ansible semblable à bien des aspects à Puppet mais avec quelques différences très intéressantes:

  • Aucun agent à installer sur les machines cibles. Ca permet de se lancer plus rapidement et plus facilement, on installe ansible et c'est parti !
  • Le déploiement et le passage de commande est réalisé via ssh ce qui permet de ne pas tout le temps être en root
  • Possibilité de lancer facilement des commandes shell sur tout ou partie de notre plateforme. Du genre un ping ou un apache status chose qui n'est pas facile via Puppet
  • Ecrit en python plutôt qu'en ruby (mais ça c'est personnel :)
  • Bien plus simple à prendre en main que Puppet

Après l'outil est encore un peu jeune et manque de certaines fonctionnalités dans la version open-source comme:

  • Avoir un dashboard pour consulter le résultat de déploiements réalisés de manière régulières (via cron par exemple). Actuellement on lance ansible il effectue ses actions et affiche le résultat sur la sortie standard. Pas de console centralisée
  • Logs d'exécution. Dans le cas où quelque chose se passe mal, le résultat affiché est très léger et oblige quasiment tout le temps à se logguer sur la machine pour voir de quoi il en retourne alors qu'avoir plus de logs et récupérés sur la machine exécutant ansible serait bien plus pratique quand même !
  • Déploiement sous Windows
Ces fonctionnalités semblent disponibles dans la version enterprise à 100$/machine/an.

Premiers pas

Assez parlé il est temps de jouer un peu avec Ansible !

Installation d'Ansible

L'installation est facile et prévue pour à peu près toutes les distributions Linux et même pour Mac sur la page getting started.

Pour ma part j'ai installé ça via un PPA:

On ajoute ça à nos sources:
deb http://ppa.launchpad.net/rquillo/ansible/ubuntu precise main 

deb-src http://ppa.launchpad.net/rquillo/ansible/ubuntu precise main

Et puis:
sudo apt-get install ansible

Et c'est bon !

Premiers tests

Pour faire nos tests nous allons initier une machine virtuelle via Vagrant:
vagrant init precise64

Et on lance notre vm:
vagrant up

Une fois la machine up nous allons faire un simple test de connexion à notre VM. Tout d'abord créons un dossier ansible à côté de notre Vagrantfile afin de travailler:
mkdir ansible && cd ansible

On créé ensuite le fichier hosts qui va contenir la liste des machines de notre plateforme qui ne contient qu'une machine:
127.0.0.1 ansible_ssh_port=2222 ansible_connection=paramiko

Le paramètre "ansible_ssh_port" permet de spécifier un port différent du port 22 par défaut pour se connecter via SSH. Le port 2222 est une redirection du port 22 de notre VM qui est ouvert automatiquement par Vagrant.

Le paramètre "ansible_connection" a été nécessaire pour moi afin de contourner un bug qui avait pour conséquence que Ansible restait bloqué après la connexion.

Pour info ce type de connexion est le type par défaut à partir d'Ansible 1.3.1 (j'ai fait mes tests avec la v1.2.2).


Et ensuite on lance le module "ping" (inclus dans Ansible) sur l'ensemble des machines de notre plateforme (donc juste en local):
ansible all -i hosts -m ping -u vagrant -k

Les options utilisées:
  • all: permet de préciser à quel groupe/machine appliquer la commande ou le module
  • -i : pour préciser le fichiers hosts à utiliser (par défaut /etc/ansible/hosts)
  • -m: le nom du module à exécuter
  • -u: l'utilisateur utilisé pour la connexion
  • -k: demander le mot de passe sur l'entrée standard
Et le résultat:
localhost | success >> {

    "changed": false, 

    "ping": "pong"

}

Ça marche ! On va maintenant exécuter une commande Unix quelconque, par exemple "uptime". Cela se fait via la commande suivante:
ansible all -i hosts -m shell -a "uptime" -u vagrant -k

Et le résultat:
localhost | success | rc=0 >>

 19:26:06 up 17 min,  2 users,  load average: 0.28, 0.33, 0.32


Tout fonctionne on va maintenant créer un module afin d'organiser un peu notre travail.

Structure d'un rôle

Les modules se nomment dans Ansible des playbook et représente en gros une liste de tâches au format YAML.

D'après la page Best practices nous allons créer quelques fichiers à la racine de notre dossier ansible:
  • Un fichier nommé "production" qui va contenir la liste de nos serveurs de production en l'occurrence uniquement les lignes suivantes:
[application-server]

127.0.0.1 ansible_ssh_port=2222 ansible_connection=paramiko

Nous allons également déclarer un playbook maître qui aura pour seule fonction d'inclure les autres playbooks afin de mieux séparer les choses:
  • site.yml:
- include: appservers.yml

Et notre fichier appservers.yml contenant les différents rôles de nos serveurs d'application:

- hosts: application-server
 
  roles:
  
    - tomcat8


Et maintenant la structure standard d'un rôle:

├── appservers.yml
├── production
├── roles
│   └── tomcat8
│   ├── files
│   ├── handlers
│   ├── tasks
│   └── templates
└── site.yml


Quelques explications:

  • Sous le dossier roles, un dossier pour chaque rôle (tomcat8 par exemple)
  • Ce dossier contient des sous-dossiers:
    • tasks: le fichier principal contenant la liste des tâches associées au rôle tomcat8
    • files: des fichiers destinés à être copié en tant que tels sur les serveurs cibles
    • handlers: les handlers utilisés par nos tâches (on verra un handler en détail un peu plus tard)
    • templates: les templates permettant de générer des fichiers instanciés en fonction des variables du serveur
C'est tout pour cette fois-ci dans le prochain article on réalisera un playbook permettant d'installer Tomcat 8 sur Ubuntu 12.04 !

Edit: l'article 2 vient d'être publié !


Post 13/52

dimanche 1 septembre 2013

[Java] Parallélisme et Immutabilité (1/2)



Ces derniers temps j'ai passé pas mal d'entretiens en Java et je me suis rendu compte qu'il s'agissait toujours des même questions qui revenaient.
Voici donc une petite série sur les questions les plus classiques et comment y répondre.
Pour débuter nous allons parler de parallélisme et d'immutabilité un sujet très classique dans les entretiens.

Souvent le sujet sera introduit de la manière suivante:

Vous voulez paralléliser votre code, comment faites-vous ?

Réponse simple et efficace: en utilisant des threads. Et à partir de là ça se gâte en général !

A quoi faut-il faire attention lors de l'utilisation des Threads ?

Le code utilisé avec des Threads doit être "Thread-Safe" afin d'éviter des incohérences dans le résultat du code.
En particulier lors de l'écriture et de la lecture de valeurs il arrive bien souvent que l'on tombe sur des incohérences telles que:
  1. La valeur lue n'est pas la dernière valeur écrite en mémoire. Cela est du au fait que les threads disposent de leur propre cache et ne le synchronise pas forcément avec la mémoire centrale où est stockée la valeur.
  2. La valeur écrite par un Thread est écrasée par un autre.
Voici un exemple de code pouvant éventuellement (cela dépend beaucoup de la machine, de la JVM et de l'OS) montrer le problème 1:


Résultat: Le script ne se termine jamais car le thread ne voit pas que le champ keepRunning vient de passer à false


Et un autre pour le cas 2:


Résultat:


On voit que le thread 1 se lance et fait ses 10 boucles sans aucun problème.
A la fin de son exécution count vaut 10 ce qui est normal.

Malheureusement le thread 2 ne prend pas la suite car il a déjà démarré il y a quelques temps a récupéré la valeur de count qui valait alors 0 mais n'a pu faire son incrément qu'à la fin de l'exécution du thread 1.

Contrairement à ce qu'on pourrait croire l'opération "count++" n'est pas atomique, il s'agit d'une lecture puis d'une écriture dans le champ count.

Dans le cas présent le thread 2 a pu lire mais pas écrire la valeur dans count. Il ne le fait qu'à la toute fin de la boucle de t1. En fait il écrit sa valeur juste avant que t1 n'écrive "10" dans count.
Cela explique pourquoi t2 continue avec 11 au lieu de 2 s'il avait écrit après la fin de t1.

Dans tous les cas il n'a pu incrémenter correctement count et cela se voit sur le résultat final avec un count valant 19 au lieu de 20 si tout s'était déroulé normalement.


Comment éviter le problème de rafraîchissement de cache d'un Thread ?

Dans le cas présenté ci-dessus notre paramètre "keepRunning" est un paramètre servant à contrôler la fin d'une boucle. Typiquement dans ce cas le plus simple est d'utiliser le mot clé "synchronized".

Pour faire simple ce mot clé permet d'indiquer à la JVM que le champ concerné sera accédé par différents threads et donc de stocker cette valeur dans la mémoire centrale et non dans le cache de chacun des threads.

Le cas d'utilisation typique est de mettre à jour un flag dans un thread et de le lire dans un autre:





Ce mot clé ne permet pas de résoudre le problème n°2 car il ne rend atomique que le get et le set et pas une combinaison des deux (ce qu'est le "count++").

Il n'est pas pertinent non plus d'utiliser le mot clé volatile dans certains cas:
  • Le champ est déclaré "final" (voir la seconde partie sur l'immutabilité)
  • Le champ n'est accédé que par un seul thread
  • Le champ doit être protégé pour des accès complexes (comme dans notre exemple n°2).

Comment éviter le problème d'écrasement d'une valeur par un autre thread ?


La façon la plus simple d'éviter le problème n°2 est d'utiliser le mot clé "synchronized" qui permet de limiter l'exécution d'un bloc de code à un seul thread à la fois:





Le problème de l'utilisation du mot clé synchronized est qu'il induit un lock bloquant les autres threads ce qui est mauvais pour les performances et la scalabilité car il constitue un véritable goulet d'étranglement limitant le passage à un seul Thread à la fois.


Une autre solution est de n'échanger entre les threads que des objets immutables qui évitent les locks et permettent d'obtenir des résultats corrects.

Mais ça on le verra dans la seconde partie de l'article qui arrive bientôt ! (... :)


Post 12/52

mercredi 28 août 2013

Play Framework et les Tests Unitaires



Depuis quelques jours, je joue avec Play!, un framework web Java.
Il possède plusieurs avantages forts sympathiques je trouve:

  • Stateless
  • REST
  • Asynchrone
  • Intgérant nativement Junit
Et c'est de ce dernier point en particulier que je vais parler aujourd'hui car l'intégration n'est pas si native que cela et je suis tombé sur plusieurs bugs gênants.

play test ne fait rien


La méthode conseillée pour lancer les tests est la commande "play test" mais malheureusement avec la version 2.1.3, cette commande ne teste absolument rien. Gênant ce bug...
Pour contourner cela il est nécessaire d'ajouter dans le fichier project/Build.scala les lignes suivantes:


val appDependencies = Seq(
    // Add your project dependencies here,
    javaCore,
    javaJdbc,
    javaEbean,
    "play" %% "play-test" % play.core.PlayVersion.current % "test" exclude("com.novocode", "junit-interface"),
    "com.novocode" % "junit-interface" % "0.9" % "test"
)


Ce problème devrait être corrigée dans la 2.1.4 qui ne devrait pas tarder à sortir.

play test se bloque lors des tests IHM


Il est possible avec Play! Framework de réaliser des tests fonctionnels en testant directement une page de notre application. Pour cela on utilise un testbrowser (cf la documentation sur le sujet).

Malheureusement si l'on fait cela avec la version actuelle de Play! Framework cela va bloquer entièrement la commande "play test" qui ne sera donc plus très utile.

Cela est dû à une incompatibilité avec la version de JQuery livré avec Play! Framework d'après ce bug.
La seule façon de débloquer cela est de télécharger la version 1.8.3 de jquery et de l'ajouter dans le dossier public/javascript en remplacement de la version 1.9.0 (ne pas oublier de mettre à jour vos pages aussi).

Lancer les tests unitaires depuis Eclipse


La commande "play test" est sympathique mais il arrive très régulièrement que l'on souhaite lancer uniquement un test ou une classe de tests depuis notre Eclipse et là malheureusement cela ne marche pas comme attendu à cause de l'erreur suivante:


java.lang.IllegalStateException: Class [class play.db.ebean.Model] is enhanced and [class models.Company] is not - (you can not mix!!)



Pour corriger cela il est nécessaire de télécharger le jar d'ebean et de l'ajouter en tant que paramètre par défaut dans Eclipse. Pour cela il est nécessaire d'aller dans Preferences > Java > Installed JRE > Edit et d'ajouter la ligne suivante:


-javaagent:/path/to/ebean/ebean-2.7.3-agent.jar



Et voilà ça devrait mieux aller !


Vraiment ? Pas dans tous les cas en fait. Il peut arriver que suite à cela un test soit cassé car lors d'un select en base via Ebean qui renvoie un objet avec un champ null.
Dans mon cas il s'agissait d'un champ Text (ou @Lob pour Ebean) qui était systématiquement vide alors que l'objet inséré le contenait bien.

Pour corriger cela il faut passer le champ concerné en private et générer soit même les getter/setter au lieu de laisser Play! le faire tout seul.
Et c'est tant mieux, je n'aime pas le fait d'avoir l'ensemble de mes champs public ça casse un peu le principe de l'encapsulation.

Fichier "init-data.conf" non trouvé


Si vous avez suivi les tutoriels du site Play! Framework vous avez vu que l'on peux ajouter facilement des données aux tests ou à l'application en cours de développement en créant un fichier Yaml dans le dossier conf/ et contenant l'ensemble des éléments à créer en base.

Le problème étant que si l'on fait les tests ensuite via Junit dans Eclipse il ne va jamais trouver ce fichier et donc ne va pas précharger votre base de données...

Pour corriger cela il faut ajouter le dossier conf au classpath d'Eclipse car celui-ci n'est pas ajouté lors de la commande "play eclipse".

Pour l'ajouter il suffit de faire un click droit sur le dossier conf/ dans le projet et choisir "Build Path" > "Use as Source Folder".

Je veux le coverage de mon code !


Maintenant que l'on a des tests qui fonctionnent que ça soit via la commande play test ou dans Eclipse on aimerait bien avoir également la couverture de code que l'on teste. Nous allons utiliser jacoco pour générer notre coverage.

Pour cela il faut ajouter plusieurs éléments à notre configuration:

  • Dans le fichier project/plugins.sbt ajouter les lignes suivantes:
libraryDependencies ++= Seq(
  "org.jacoco" % "org.jacoco.core" % "0.5.9.201207300726" artifacts(Artifact("org.jacoco.core", "jar", "jar")),
  "org.jacoco" % "org.jacoco.report" % "0.5.9.201207300726" artifacts(Artifact("org.jacoco.report", "jar", "jar")))

addSbtPlugin("de.johoop" % "jacoco4sbt" % "1.2.4")
  • Dans le fichier project/Build.scala:
  • Ajouter sous les import déjà existant les lignes suivantes:
import de.johoop.jacoco4sbt._
import JacocoPlugin._
  • Ajouter sous le bloc "val appDependencies = Seq(...)" une ligne:
lazy val s = Defaults.defaultSettings ++ Seq(jacoco.settings:_*)


  • Puis modifier le dernier bloc pour qu'il ressemble à cela (attention à bien ajouter le paramètre settings = s):
val main = play.Project(appName, appVersion, appDependencies, settings = s).settings(
    
    parallelExecution     in jacoco.Config := false,    
    jacoco.reportFormats  in jacoco.Config := Seq(XMLReport("utf-8"), HTMLReport("utf-8")),    
    jacoco.excludes       in jacoco.Config := Seq("views.*", "controllers.Reverse*", "controllers.javascript.*", "controllers.ref.*", "Routes*")
  )



Et voilà la couverture peut maintenant être générée via la commande:

play jacoco:cover



L'ensemble des fichiers seront placés dans le dossier /target/scala-2.9.1/jacoco/html.


Petit exemple du look:





Post 11/52

lundi 26 août 2013

QTodoTxt: une application pour todo.txt simple, rapide et multiplateforme




Aujourd'hui j'aimerai vous parler d'un sujet qui me tient particulièrement à coeur à savoir l'organisation personnelle et en particulier "Getting things done" (GTD).


J'ai découvert ce système et lu le livre allant avec il y a 3 ans alors que je cherchais une méthode un peu plus évoluée afin de gérer mes actions et projets au mieux. Cela m'aide beaucoup afin de ne pas tout reporter au lendemain ni de conserver en tête toute la liste de choses que j'ai à faire.
Du coup cela me libère l'esprit et me permet de me concentrer sur ce que je fais à l'heure actuelle. En plus de ne rien oublier, je suis plus efficace dans ce que je fais, que du bénef !


Par contre il me manquait un outil me permettant d'appliquer cette méthode au quotidien. Mon cahier des charges était assez simple (enfin je pensais):

  • Libre
  • Fonctionnant sur Android, Linux et Windows
  • Permettant de synchroniser mes tâches entre mes différents appareils
  • Avec une interface utilisateur simple
En ce qui concerne la partie mobile et la synchro (via Dropbox) j'ai trouvé assez rapidement avec l'outil Todo.txt Touch de Gina Trapani qui est la partie mobile de todo.txt. Payant mais open-source, il fonctionne bien et est maintenu par une communauté active.
De plus l'application n'a pas une structure très complexe, uniquement 2 fichiers texte dont un optionnel:

  • todo.txt: contenant l'ensemble des tâches
  • done.txt: contenant l'ensemble des tâches terminées (optionnel)
Je me retrouvais donc avec 2 fichiers synchronisés sur mes ordinateurs mais rien pour les lire de manière un peu sympa...

Après moultes recherches où j'ai trouvé des interfaces web (un peu chiant de devoir installer un apache absolument partout), des outils pour Windows uniquement ou seulement pour Linux je suis tombé sur la perle rare: QTodoTxt.

Un outil simple, multi-plateforme codé en python + Qt, open-source et rapide. Bref il semblait idéal sauf qu'il:

  • n'était plus maintenu depuis 2011
  • avait quelques bugs gênants (pas de support de l'utf8,...)
  • manquait de quelques fonctionnalités (date de création, sauvegarde automatique, auto-archivage,...)
Heureusement le code étant opensource et ayant toujours voulu jouer un peu avec du python, je me suis dis pourquoi pas, adoptons une application !

Première fois et tout se passe bien , j'ajoute des fonctionnalités, des paquets binaires, je corrige quelques bugs et j'ai même reçu mes premiers rapports de bug d'utilisateurs externes.

C'est sympa de se dire que mon application est utile à d'autres.

Du coup après 2 versions l'application permet maintenant de gérer les URLs dans les tâches, les dates de fin, la sauvegarde automatique, l'archivage automatique et la correction des quelques bugs gênants.


Même si je ne suis pas dessus en permanence je m'en sers tous les jours et elle remplie bien son but, simple,rapide et efficace!


N'hésitez pas à la tester vous aussi !

Post: 10/52

samedi 17 août 2013

Compilation de lien n°3



Ca fait longtemps que je n'ai rien publié, mille excuses !

On est reparti pour un tour avec plein de nouvelles idées et de truc sympas à découvrir. Pour le moment on va commencer doucement avec une petite collection de liens intéressants.

  • http://colorschemedesigner.com/ : Si comme moi vous galérez toujours pour trouver des couleurs qui s'accordent bien ensemble ce site est fait pour vous. À partir d’une couleur donnée et du schéma choisi (monochrome, complémentaire, triade,...), l’application déduit les différentes teintes pouvant s’accorder entre elles. Toujours pratique !
  • Nginx vient de devenir le nouveau serveur web le plus utilisé parmi les sites du Top 1000 d'après cet article de w3techs.com. Va vraiment falloir que je teste ça !
  • Twitter: un article passionnant sur l'architecture utilisée par Twitter pour gérer 150 millions d'utilisateurs.
  • Un article donnant quelques conseils pour bien réussir un entretien (on y reviendra sur ce sujet :) et pas mal de liens utiles.
  • Dernier lien mais pas des moindres, il s'agit de RunDeck, un outil permettant d'automatiser des workflows à travers une ferme de serveurs. Puppet est super sympa mais malheureusement il n'est pas possible de demander à déployer d'abord le serveur A puis le B. RunDeck permet de faire ça et bien plus encore !
Et voilà c'est tout pour le moment !

Post: 9/52

lundi 18 mars 2013

Remplacer Google Reader en 5 minutes et gratuitement


L'annonce de la part de Google de la fermeture du service Reader au 1er juillet 2013 en a perturbé plus d'un car en 7 ans d'existence Goggle Reader s'était imposé comme la solution n°1 pour consulter ses flux RSS et Atom.


Comme tout le monde je me suis mis à chercher des alternatives à Google Reader, il en existe beaucoup (Feedly, Netvibes, NewsBlur,...) mais aucune ne me convenait. Pourtant je ne demande pas grand chose:

  1. Une interface web pas trop chargée
  2. Une appli Android
  3. Une appli Android qui fonctionne en mode offline (les joies du transport en commun)
Et c'est sur le point 3. que ça bloque, je n'ai rien de trouvé de très convaincant mis à part un produit open-source Tiny tiny RSS qui se charge de tout le travail et dispose même d'un client Android gratuit et fonctionnant en mode offline, génial !

Le seul défaut et pas des moindre pour moi est qu'il faut l'installer sur son propre serveur... Pas envie de faire de l'administration de serveur le soir chez moi j'en fais déjà assez au travail, et encore moins envie de payer pour la lecture de flux RSS (je n'ai qu'une cinquantaine de flux).


Et on va faire tout ça en 3 étapes:

  1. S'inscrire à OpenShift
  2. Installer Tiny Tiny RSS
  3. Utiliser l'application Android

Inscription à OpenShift

OpenShift est la solution de PaaS de Redhat (un peu comme Google App Engine). Le gros avantage est qu'elle dispose d'une offre gratuite pour une utilisation raisonnée et c'est de ça que l'on va profiter maintenant.
On commence d'abord par s'inscrire sur OpenShift :



On remplit les champs, on valide l'email et on arrive alors à une page demandant de créer une application. Inutile d'aller plus loin on fera tout ça automatiquement par la suite.


On passe à l'étape 2.

Installation de Tiny Tiny RSS

Installation de rhc

Pour installer notre application Tiny Tiny RSS il faut installer l'outil rhc. Voici comment faire sur Linux Ubuntu (pour les autres systèmes d'exploitation voir la page RedHat dédiée):


$ sudo apt-get install ruby-full rubygems git-core
$ sudo gem install rubygems-update
$ sudo update_rubygems
$ sudo gem install rhc
$ rhc setup


Pour la dernière commande il faudra entrer le nom d'utilisateur (l'adresse mail) et le mot de passe choisit lors de la première étape.

Création de notre application Tiny Tiny RSS

On va ensuite utiliser la commande rhc pour créer automatiquement notre application grâce au travail de who-me :


$ rhc app create <app name> php-5 postgresql-8 \
--from-code=git://github.com/who-me/ttrss-fast-deployment.git
$ rhc cartridge add cron-1.4 -a <app name>


Et voilà l'installation de Tiny Tiny RSS est terminée et on peut se connecter à notre application à l'url http://<app name>-<your namespace>.rhcloud.com :





Le couple nom d'utilisateur / mot de passe par défaut est admin / password (à changer immédiatement bien sûr...).

Configuration

Nous avons notre application de gestion des flux RSS tout propre, toute neuve mais elle fait un peu vide quand même ! Pour la remplir nous allons exporter nos données de Google Reader. Pour cela utiliser le service Google Takeout qui vous permettra de récupérer vos données sous la forme d'une archive zip.

Le fichier qui nous intéresse dans cette archive se nomme subscriptions.xml et va nous servir à intégrer dans Tiny Tiny RSS tous nos flux RSS.

Pour cela dans Tiny Tiny RSS aller dans "Actions..." > "Preferences" > "Feeds" > "OPML" et sélectionner le fichier subscriptions.xml :





Tant que l'on est dans les préférences on va également activer les API externes pour le client Android Dans l'onglet "Preferences" au paragraphe "General" changer la ligne "Enable external API" à "Yes".


Et voilà terminé pour l'installation de l'application ! On passe à la partie Android !

Utilisation de l'application Android

Sur Google Play installer l'application nommée TTRSS-Reader de Nils Braden (ne pas prendre l'autre, elle ne fonctionne que 7 jours) et l'installer.

Au niveau des préférences de l'application entrer l'url de votre serveur (http://<app name>-<your namespace>.rhcloud.com normalement), le nom d'utilisateur et le mot de passe. N'activer pas le mode "Lazy Server" j'ai eu des problèmes avec. De même ne mettez pas de quote (') dans le mot de passe cela semble poser problème.


Et voilà vous avez un client Android qui fonctionne en mode déconnecté:





Bon, je l'admet les cinq minutes c'était uniquement pour appâter le chaland mais malgré tout vous voilà avec une solution viable, gratuite et qui ne s'arrêtera pas le 1 juillet !


Amusez-vous bien !


Post 8/52