29 avr. 2014

Favicon was a pain

Yes, the pain is now gone. Use this incredible site: http://realfavicongenerator.net/

It can treat SVG too. Sooo, niiice!

27 avr. 2014

tig - git history made simple on the CLI

tig, git in reverse, is a nice CLI that allows to browse your git history with a clean ncurse interface.

Installing it on OSX:
brew install tig
I've made a simple video of its basic usage:

Meteor 101: a nice presentation from Sacha Greif

Sacha Greif is one of the authors of the book 'Discover Meteor'. At the last Meteor DevShop of April, Sacha made a nice introduction to Meteor. He has published his demonstration based at: meteor101.com.


25 avr. 2014

I'm a student... A Famo.us one.

Yes! I'm a student. It's been a long time since I was one. That's refreshing.

It starts with a beautiful animation. It's going to be a great time.

23 avr. 2014

Global var in CoffeeScript for Meteor

Just a reminder as I've struggled a bit on it. Meteor.js uses a nice exposing feature of global vars in packages. On the other hand, CoffeeScript forbids the use on inexplicit variable by creating an anonymous namespace, therefore preventing global scope pollution.

OK... but how do we marry back this to approach. Sugar your coffee provides a nice answer:

  • In Javascript:
    myglobal = new Global('something');
  • In Coffeescript (use the this operator: the @):
    @myglobal = new Global 'something'

21 avr. 2014

RoboMongo, the ultimate graphic admin tool for MongoDB and Meteor

Introduction

When using MongoDB, I always end up on the CLI. Though, it is my natural way of interacting with codes, a nice UI may give me some perspective. It becomes more important when I start using a full stack JS like MEAN or Meteor, ...: "how did they structure their models?" is one of my first question and introspection. 

Robomongo from Paralect is a free open source administration tool for MongoDB. It is available on Linux, Windows and OSX. And, it is the perfect tool for playing with your instances.

Installation on OSX

As always, I'm using Homebrew and its Cask extension. Using the CLI over the basic installation DMG has the advantage of being reproducible when setting up many development environment granting the capability to use DevOps workflow instead of manual procedures. And... it is so easy:
brew cask install robomongo

Configuring for Meteor

Now, just fire up one of your JS full stack project. If you have followed my previous tutorial "Meteor walktrough: Samples from JSConf 2013", you should have an already ready for running project.

When executing Robomongo, it asks you where lays your MongoDB instance:
Just hit "Create" and use the port 3001 if you haven't modified your default MongoDB instance in Meteor:
Save it and connect to it. As you can see it on the first screenshot, you can browse your instance, use the an internal CLI to perform new operations, ... Note that the CLI has some interesting features such as completion that drastically increase the usability and the data mining.


Meteor walktrough: Samples from JSConf 2013

Introduction

Meteor is a full stack JS framework: JS is used on the server side as well as on the client side. This allows a code mutualisation between this generally separated world. Meteor really shines in its way of handling this mutualisation. It allows you to specify where your code will be used. It relies on a Node and MongoDB.

In October 2013, Emily Stark, one of the core developper behind Meteor, has presented at the Asia JSConf 2013 a nice tutorial. I simply provides hereafter the transformed files in CoffeeScript, Jade and Stylus that will help you out understanding and playing with it while watching the associated video:

Settings

First, you need a running installation of MongoDB and Node. On OSX, it is done using Homebrew:
brew install mongodb node
Now, it is time to import Meteor:
curl https://install.meteor.com/ | sh
Note: The regular installation through NPM does not import the sample application for the generators. Therefore, I recommend using the regular automated shell script.

Meteor comes with an handy package management named Meteorite and its official repository Atmosphere. In essence, its purpose is to handle all packages that merges the world of the server side, NPM, and the world of the client, Bower. It is installed as regular Node package:
npm install -g meteorite

Preparing the playground

Now create a sample app:
mrt create JsConfAsia
cd JsConfAsia
Remove unused package and add some nice other ones:
mrt remove autopublish
mrt add meteor-jade
mrt add meteor-coffeescript
mrt add meteor-bootstrap-3
mrt add meteor-stylus
Just remove the created file, that we are going to recreate:
rm JsConfAsia.*

Replacing the files

Now, in order to better follow the nice video, I propose you this set  of simple file:
  1. JsConfAsia.styl
    body
      font-family: Helvetica, Arial, sans-serif
    p
      margin: 0
      padding: 0
    li
      padding-bottom: 5px
    
  2. JsConfAsia.jade.html
    head
      title JsConfAsia
    body
      .container
        +header
        +talksList
    
    template(name='header')
      h2 Judge jsconf.asia talks
      h3 Be ruthless
    
    template(name='talksList')
      ul
        each talks
          li
            p: <strong>#{title}</strong> by #{speaker} (#{votes} votes)
            .btn-group.btn-group-sm
              button.btn.btn-success.upvote
                <span class="glyphicon glyphicon-thumbs-up"></span> +1
              button.btn.btn-danger.downvote
                <span class="glyphicon glyphicon-thumbs-down"></span> -1
    
  3. JsConfAsia.jade.html
    Talks = new Meteor.Collection 'talks'
    
    Meteor.methods
      upvote: (talkId) ->
        talk = Talks.findOne talkId
        Talks.update talkId, {$set: {votes: talk.votes + 1}}
      downvote: (talkId) ->
        talk = Talks.findOnedOne talkId
        if talk.votes isnt 0
          Talks.update talkId, {$set: {votes: talk.votes - 1}}
    
    if Meteor.isServer
      Meteor.publish 'talks', ->
        Talks.find()
    else if Meteor.isClient
      Meteor.subscribe 'talks'
      Template.talksList.talks = ->
        Talks.find {}, {sort: {votes: -1}}
      Template.talksList.events
        'click .upvote': ->
          Meteor.call 'upvote', @_id
        'click .downvote': ->
          Meteor.call 'downvote', @_id

Adding some sample data into MongoDB

Meteor eases the use of MongoDB shell with this little command:
mrt mongo
Now, simply cut and paste the following value:
db.talks.insert({title: "Clone Toy Story in 24h with CSS", speaker: "Lea Verou", votes: 0});
db.talks.insert({title: "Enhance! Enhance!", speaker: "That Adobe guy", votes: 0});
db.talks.insert({title: "Templates: the child of Satan", speaker: "Peter Hunt", votes: 0});
To exit and come back to your shell CLI, hit the classic key stroke: ctrl+c.

Execute Meteor

Just execute the basic command:
mrt
And open your browser of choice on http://localhost:3000.

This should provide the following reactive and multi-users web app in less than 100 lines of codes:
Classy!

20 avr. 2014

Meteor + Famo.us: Made for each other

A nice introduction video on integrating Meteor and Famo.us.

Note: A plugin named famono already exists on Atmosphere for easing the integration.

Jade syntax highlighting for meteor-jade in Vim

Owing to a hack, your initial Jade file in Meteor using Meteor-Jade needs to be called with a double extension myApp.jade.html. This breaks the basic syntax highlighting mechanism based on file extension. Thankfully, we can teach Vim to handle these weird extensions. Here is how I set it up in my ~/.vimrc:
Bundle 'digitaltoad/vim-jade'
au BufNewFile,BufRead,BufReadPost *.jade.html set filetype=jade

Note: I've shared my dotfiles on Github: https://github.com/PEM--/dotfiles

19 avr. 2014

Nice indentation guides in Vim

When you use language that rely on indentation (such as Python, CoffeeScript, Sass, Stylus, JadeSlim, ...), having indentation guide in Vim prevents you from headaches. indentLine does just that in a nicely fashion:

Installing it with Vundle is a one liner in your ~/.vimrc:
Bundle 'Yggdroot/indentLine'

Note: I've shared my dotfiles on Github: https://github.com/PEM--/dotfiles

Choose your colors while editing code in Vim

Choosing the appropriate colors on your UI is a delicate job. ColorV and colorizer are 2 plugins for Vim that help a lot. I use them on almost every kind of source that I manipulate.

Importing them in you ~/.vimrc is pretty easy if you use a plugin importer. I'm using Vundle and here is the extract that imports these plugins:

Bundle 'Rykka/colorv.vim'
let g:colorv_preview_ftype='css,html,js,coffee,sass,scss,less,styl,svg'
Bundle 'lilydjwg/colorizer'

Note: I've shared my dotfiles on Github: https://github.com/PEM--/dotfiles

15 avr. 2014

Source code of the FamousBird demo

The source code of the FamousBird demo, a clone of FlappyBird using Famo.us is available on Github: https://github.com/DrClick/FamousBird.


Some notes on Famo.us

Note : These samples are written in CoffeeScript.

Listen to window resizing:
Engine.on 'resize', ->
  surface.setContent
    'dimensions:' + '<br>' +
    'width : ' + window.innerWidth  + 'px ' + '<br>' +
    'height: ' + window.innerHeight + 'px'

Listen on click event on the entire screen:
Engine.on 'click', (event) ->
  surface.setContent
    'click position:' + '<br>' +
    'x :' + event.clientX + 'px ' + '<br>' +
    'y :' + event.clientY + 'px'

Add an EventHandler on a Surface:
eventHandler = new EventHandler()
surface.pipe eventHandler
eventHandler.on 'click', -> alert 'Click from the event handler'

Create a Surface with its true size (the exact size of its content):
surface = new Surface
  size: [true, true]
  content: 'Hello World'
  classes: ['red-bg']

View is a widget container for Surface. They can be attached to the RenderTree and can handle events:
mainContext = Engine.createContext()
view = new View()
surface = new Surface
  size: [200, 200]
  content: 'Hello World'
  classes: ['red-bg']
  properties:
    lineHeight: '200px'
    textAlign: 'center'
surface.pipe view
view._eventInput.on 'click', -> alert 'Primary Surface Clicked'
view._add surface
mainContext.add view

Fill a ContainerSurface with a ScrollView containing 100 Surface:
container = new ContainerSurface
  size: [400, 400]
  properties:
    overflow: "hidden"
surfaces = []
scrollview = new Scrollview()
for idx in [0...100]
  temp = new Surface
    size: [undefined, 50]
    content: "I am surface: " + (idx + 1)
    classes: ["red-bg"]
    properties:
      textAlign: "center"
      lineHeight: "50px"
  temp.pipe scrollview
  surfaces.push temp
scrollview.sequenceFrom surfaces
container.add scrollview
mainContext
  .add new Modifier
    origin: [.5, .5]
  .add container


13 avr. 2014

Examples of native interface recreated with Famo.us

Capptivate has aggregated a set of examples created with Famo.us. Some of them are inspired from native interfaces, some are completely new ones.

A site to bookmark: http://capptivate.co/

Famo.us with Gulp.js and Browserify in CoffeeScript

Introduction

Famo.us is a new framework with a new radical approach to HTML5 development. Basically, everything is treated as surfaces which are seen by the browser as accelerated virtual DOM components. This is all achieved under the JS files and not via CSS3 files via transforms and animations. Therefore, it avoids pollution of your CSS which is solely used for theming. As virtual DOM, the real HTML's DOM is not polluted either with DIVs inserted only for animation purposes. The animations and screen dynamics are kept separated in your JS files. But, it is not all that is provided out-of-the-box. Every tricks that needs to be inserted in our codes for being compatible with all mobiles, tablets and desktops have been inserted directly in the library. HTML5 starts to really shine using Famo.us.

Why an HelloWorld?

Currently, Famo.us is distributed either as source file in their Github repository or as a Yeoman generator that uses Grunt. This last option is incredibly nice and will surely be the most preferred one. It is rare enough to note it: Famo.us has done a great job towards its users. There are really few frameworks which provides so much as soon as they are launched. Plus, it has been done 'state-of-the-art' for most users who like writing plain HTML, CSS and JS. Really nice. Kudos to the Famo.us team.

But, if you have read this blog entries, you should know that I don't like writing vanilla codes. I generally prefer relying on preprocessors. So, with this little tutorial, I will show you my best moves to integrate Sass, Jade, CoffeeScript and Famo.us using Gulp.js and Browserify. Once done, it becomes easy to start playing with the great examples that Famo.us provides: Collection of Famo.us examples on Github.

I've shared all the source code of this tutorial into a little Github repository: PEM--/hellofamousgulped.

Creating the folder hierarchy

The tree of files is as following:
.
├── app
│   ├── css
│   │   └── main.sass
│   ├── index.jade
│   └── js
│       └── main.coffee
├── bower.json
├── gulpfile.coffee
├── gulpfile.js
└── package.json

To create it, use this classic command:
mkdir -p app/css app/js

Import Famo.us using Bower

Now, we import Famo.us thanks to Bower. Here is the content of my bower.json file:
{
  "name": "HelloFamousGulped",
  "version": "0.0.0",
  "authors": [
    "PEM--"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "famous": "git@github.com:Famous/famous.git#v0_1_1"
  }
}
Once copied, use Bower to import Famo.us and all its submodules:
bower install

Import Gulp.js and Browserify using NPM

No JS on your desktop without the powerful Node Package Management. To import all our required build tools and plugins, use my package.json or get inspiration from it:
{
  "name": "HelloFamousGulped",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "PEM--",
  "license": "MIT",
  "dependencies": {},
  "devDependencies": {
    "gulp": "^3.6.0",
    "gulp-load-plugins": "^0.5.0",
    "gulp-util": "^2.2.14",
    "gulp-autoprefixer": "0.0.6",
    "gulp-imagemin": "^0.2.0",
    "gulp-clean": "^0.2.4",
    "gulp-cache": "^0.1.3",
    "gulp-ruby-sass": "^0.4.3",
    "gulp-connect": "^2.0.5",
    "gulp-cssmin": "^0.1.4",
    "gulp-jade": "^0.5.0",
    "gulp-concat": "^2.2.0",
    "gulp-plumber": "^0.6.1",
    "gulp-watch": "^0.5.4",
    "gulp-changed": "^0.3.0",
    "gulp-bower": "^0.0.4",
    "gulp-open": "^0.2.8",
    "coffeeify": "^0.6.0",
    "browserify": "^3.41.0",
    "deamdify": "^0.1.1",
    "vinyl-source-stream": "^0.1.1",
    "debowerify": "^0.7.0",
    "uglifyify": "^2.1.1"
  },
  "engines": {
    "node": ">=0.10.0"
  }
}
Once copied and adapted to suit your needs, let NPM do its magic:
npm install

Create the build scripts

Actually as I've already blogged about it (A gulp of coffee: your gulpfile in coffeescript), I use a JS wrapper to call Gulp.js within CoffeeScript. It has the strong advantage to shorten your Gulpfile a lot. Here is the wrapper gulpufile.js:
'use strict';
require('coffee-script/register');
require('./gulpfile.coffee');

And now, the real build script gulpfile.coffee:
'use strict'
gulp       = require 'gulp'
gp         = (require 'gulp-load-plugins') lazy: false
path       = require 'path'
browserify = require 'browserify'
source     = require 'vinyl-source-stream'

# HTML
gulp.task 'html', ->
  gulp.src 'app/index.jade'
    .pipe gp.plumber()
    .pipe gp.jade locals: pageTitle: 'Famo.us built with Gulp'
    .pipe gulp.dest 'www'

# JS
gulp.task 'js', ->
  browserify
    entries: ['./app/js/main.coffee']
    extensions: ['.coffee', '.js']
  .transform 'coffeeify'
  .transform 'deamdify'
  .transform 'debowerify'
  .transform 'uglifyify'
  .bundle()
  # Pass desired file name to browserify with vinyl
  .pipe source 'main.js'
  # Start piping stream to tasks!
  .pipe gulp.dest 'www/js'

# CSS
gulp.task 'css', ->
  gulp.src 'app/css/*.sass'
    .pipe gp.plumber()
    .pipe gp.rubySass style: 'compressed', loadPath: ['bower_components', '.']
    .pipe gp.cssmin keepSpecialComments: 0
    .pipe gp.autoprefixer 'last 1 version'
    .pipe gulp.dest 'www/css'

# Images
gulp.task 'img', ->
  gulp.src ['app/img/*.jpg', 'app/img/*.png']
    .pipe gp.cache gp.imagemin
      optimizationLevel: 3
      progressive: true
      interlaced: true
    .pipe gulp.dest 'www/img'

# Clean
gulp.task 'clean', ->
  gulp.src ['www', 'tmp'], read: false
    .pipe gp.clean force: true

# Build
gulp.task 'build', ['html', 'js', 'css']

# Default task
gulp.task 'default', ['clean'], -> gulp.start 'build'

# Connect
gulp.task 'connect', ['default'], ->
  gp.connect.server
    root: 'www'
    port: 9000
    livereload: true

# Watch
gulp.task 'watch', ['connect'], ->
  gulp.watch 'app/**/*', read:false, (event) ->
    ext = path.extname event.path
    taskname = null
    reloadasset = null
    switch ext
      when '.jade'
        taskname = 'html'
        reloadasset = 'www/index.html'
      when '.sass'
        taskname = 'css'
        reloadasset = 'www/css/main.css'
      when '.coffee', '.js'
        taskname = 'js'
        reloadasset = 'www/js/main.js'
      else
        taskname = 'img'
        reloadasset = "www/img/#{path.basename event.path}"
    gulp.task 'reload', [taskname], ->
      gulp.src reloadasset
        .pipe gp.connect.reload()
    gulp.start 'reload'

Now we are ready to code!

The app/index.jade, a Jade file that produces our www/index.html, is really kept as its minimum:
doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    title= pageTitle
    meta(name="viewport", content="width=device-width, maximum-scale=1, user-scalable=no")
    meta(name="mobile-web-app-capable", content="yes")
    meta(name="apple-mobile-web-app-capable", content="yes")
    meta(name="apple-mobile-web-app-status-bar-style", content="black")
    link(rel="stylesheet", href="css/main.css")
  body
    script(src="js/main.js")

It's Famo.us that will populate the DOM.

Now, just to reset our CSS and gives a nice clean look to our little app, here is the content of our app/css/main.sass, a Sass file that produces our www/css/main.css:
// From this gist: https://gist.github.com/trey/3524
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p,
blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em,
img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i,
center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption,
tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section,
summary, time, mark, audio, video
  margin: 0
  padding: 0
  border: 0
  font-size: 100%
  font: inherit
  vertical-align: baseline

article, aside, details, figcaption, figure,  footer, header, hgroup, menu,
nav, section
  display: block

body
  line-height: 1
 
ol, ul
  list-style: none
 
blockquote, q
  quotes: none
 
blockquote:before, blockquote:after,
q:before, q:after
  content: ''
  content: none
 
table
  border-collapse: collapse
  border-spacing: 0

// Import Famo.us's CSS
@import bower_components/famous/core/famous.css

// Real theming happens hereafter
$bgColor: #FF851B
$mainColor: white

html, body, .bgColor
  background-color: $bgColor 

body
  color: $mainColor
  font-family: Helvetica, Arial, sans-serif

Now comes the real fun. Our app/js/main.coffee, a CoffeeScript that produces the www/js/main.js single file is where are required all the dependencies. If you plan on splitting your app into multiple files or importing new Famo.us components or installing new dependencies thanks to BowerBrowserify will do all the heavy lifting importing and building everything into a single file. So, here is simple hello world in regular CoffeeScript:
Engine = require 'famous/core/Engine'
Surface = require 'famous/core/Surface'
Modifier = require 'famous/core/Modifier'

# Create the main context
mainContext = Engine.createContext()

outline = new Surface
  size: [200, 200]
  content: 'Hello world in Famo.us'
  classes: ['bgColor']
  properties:
    lineHeight: '200px'
    textAlign: 'center'

outlineModifier = new Modifier
  origin: [0.5, 0.5]

mainContext
  .add outlineModifier
  .add outline

If you haven't installed Gulp.js and CoffeeScript yet, install them globally:
npm -g install gulp coffee-script

It is now time to check our little hello world in Famo.us. Hit the next command:
gulp watch

Now, open your favorite browser at http://localhost:9000.As our Gulpfile is loaded with Livereload, you can edit the source code live and see all the magic brought to us thanks to Famo.us. You can even open this app with your tablet or smartphone. It works like a charm.

Conclusion

Famo.us brings a new interesting way of creating rich HTML5 apps that are almost as fast as native development without the burdens of redeveloping everything on each platform.

Though, with this new shift in code design, we have some old constraints that arise again. SEO, for instance. Rethinking RWD is another one. Still with this powerful framework in our hands, it is easy to figure out how. Solving this little issues is not a big deal when compared to the huge problems that Famo.us has solved.

12 avr. 2014

Famo.us docs and guides

While waiting for your inscription to the Famo.us university, Famo.us has published their API docs and some guides. That's easier than reading the jsdoc.

10 avr. 2014

Famo.us has landed on Github

Just hit: https://github.com/Famous/famous

Some documentation are available here: https://github.com/Famous/guides/tree/master/dev

Install it and start using thanks to NodeJS, NPM, Yeoman, Grunt and Bower:
npm install -g generator-famous
mkdir newProject
cd newProject
yo famous
grunt serve

9 avr. 2014

Color your logs

Log files are a pain to read. When colored a bit, you start having a better understanding of what it going on under the hood.


This is achieved via a simple tail replacement: colortail.

On OSX, hit the following command:
brew install colortail

On Ubuntu, use your favorite package system command:
sudo apt-get install colortail

Now, in your ~/.bashrc or your ~/.zshrc, add a simple aliases:
alias tail='colortail -k ~/.colortail/conf.default '

Create a ~/.colortail dir where you can put your colored theme files:
mkdir ~/. colortail

Here is my ~/.colortail/conf.default file:
COLOR brightred
{
# matches the word ERROR
^.*(ERROR|error).*$
}
COLOR yellow
{
# matches the word WARNING
^.*(WARNING|warning).*$
}
COLOR green
{
# matches the word INFO
^.*(INFO|info).*$
}
COLOR grey
{
# matches the word DEBUG
^.*(DEBUG|debug).*$
}
COLOR brightblue
{
# matches the time
^.*([0-9]{2}:[0-9]{2}:[0-9]{2}).*$
}

6 avr. 2014

Tips: Debug Saltstack States

Just hop under your current Vagrant VM and launch the SLS file locally:
vagrant ssh
sudo salt-call state.highstate --log-level=debug

5 avr. 2014

Source files of the 2 tutorials on Vagrant and SaltStack available on Github

I've uploaded my source file on Github: VagrantSaltstackNginxSample for the Vagrant and Saltstack tutorials:

  • Virtualize your servers
  • Fill up your servers automatically with goodies
  • Fill up your servers automatically with goodies

    Introduction

    In my former article "Virtualize your servers", we created a virtualized server in few command lines. But... It's empty as the void in space (or so we think...). Still, you can log in easily with:
    vagrant ssh
    It is now time to fill it with some goodies: NGINX with all the bells and whistles.

    Saltstack to the rescue

    There are many provisionner available for Vagrant: Chef, Puppet, DockerSaltstack, ... even simple bash scripts. A provisionner acts as framework for creating scripts that will fill your server wether they are physical or virtual. Note that as the servers may be virtual or physical, we will simply refers them as nodes. Nodes are the processing unit of your private cloud, wether it be a single to thousands machine.

    Depending on the provisionner you choose, you may have more power for addressing use case scenarios such as:
    • Managing a common configuration for each node with specialization for some of them.
    • Configuring IP addresses and routes for each node.
    • Managing states for each node: a state is an expected running configuration.
    • Upgrading each node and letting the other knows about it while limiting the impacts on service unavailability.
    I've chosen Saltstack as it covers these capabilities and the configuration files, the minions, that you write are simplistic and well organized.

    Make Vagrant knows about Saltstack

    Vagrant speaks Saltstack out-of-the-box. You only put in your little Vagrantfile where are stored your Saltstack files. Here, I put them in a directory named salt.
    # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
    VAGRANTFILE_API_VERSION = "2"
    
    Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
      # Name of the node
      config.vm.box = "UbuntuServer"
    
      # Import a preinstalled Ubuntu Server 12.04 LTS
      config.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-i386-vagrant-disk1.box"
    
      # Add port forwarding to access service deployed in the node
      config.vm.network "forwarded_port", host: 8080, guest: 80
    
      # Synchronized folders
      config.vm.synced_folder "salt/srv/salt/", "/srv/salt/"
      
      # Use Saltstack as provisioner
      config.vm.provision :salt do |salt|
        # Set the directory where is stored your minion
        salt.minion_config = "salt/minion"
        # Maintain states
        salt.run_highstate = true
      end
    end
    
    Note the option salt.run_highstate = true. It tells  Vagrant to ensure the node state whenever it is executing it.

    Here comes the minions

    There are 2 ways of using Saltstack: locally or as a server which acts as a repository of minions. In our simple example, we use the most basic way, the local incarnation: masterless. Therefore, the salt/minion file is kept as its bare minimum:
    # We run in masterless mode
    master: localhost
    # We use the local file directory
    file_client: local
    We use the default Saltstack directory structure to store our minion that will install NGINX:
    .
    ├── Vagrantfile
    └── salt
        ├── minion
        └── srv
            └── salt
                ├── top.sls
                └── webserver.sls
    
    The top.sls file is your entry file to the installation. Here, there is only one formula. Thus, it is pretty straightforward:
    base:
      '*':
        - webserver
    
    The webserver.sls is called by the top.sls. It contains the formula to install and run NGINX as a service:
    nginx:
      pkg:
        - installed
      service:
        - running
        - require:
          - pkg: nginx

    Get ready!

    Now, it's time to fire up everything. If you have just followed my previous tutorial "Virtualize your servers", you should already have downloaded the node's OS. We will destroy it. Yes. Destroy it. This will not re-download the node's OS. It will simply destroy its current customized image. Then, we will rerun Vagrant with our new and fresh configuration. This will do the following:
    • Re-configure the node.
    • Bootstrapping Saltstack into it.
    • Launch Saltstack so that:
      • It install NGINX using the node's OS package manager, apt-get in this case.
      • Launch NGINX as a service.
    vagrant destroy
    vagrant up
    Now, fire up your browser of choice and use the following URL: http://localhost:8080. This should display the NGINX default page just as if you had install it on a regular Ubuntu server.

    Next steps

    Vagrant and Saltstack are an incredibly powerful combo. In this example, I've made you destroy and reinstalled the node. It was only to ensure a clean state. While creating your server, you don't need to recreate everything and restart your node. Using the states provided by Saltstack, you just modify your SLS files and reprovision the states as you develop them. Iteration are done in a matter of seconds with the command:
    vagrant provision
    
    You can install other services as easily. There are some already prepared formulas that you can directly import or take inspiration from in the Saltstack formulas repository.

    3 avr. 2014

    Virtualize your servers

    Introduction

    Virtualizing a server has many advantages over installing real servers. First, you can have many installments for testing or replicating existing ones. Second, it helps you develop installation scripts which will help you on your next projects.

    OSX optional installations

    OSX comes with no package manager except the AppStore. Though, it does the required common uses for casual users, it fall short when you need hundreds of tools. Thankfully, Brew is up to the task... if you are not too reluctant using the command line. Its installation is really simple:
    ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
    You have now access to almost every free and open source available packages.

    Now, you can install an access to some already build packages as well as some proprietary software using Cask:
    brew tap phinze/cask
    brew install brew-cask
    
    Here, you are. No more search attempts for finding a software. Almost every installations are available in a single command. If you don't know the name of the package, you simply search it on the command line. Here's an example for Firefox:
    brew cask search firefox
    ==> Exact match
    firefox
    ==> Partial matches
    multifirefox

    Installing VirtualBox

    VirtualBox is a free and well maintained virtual machine, sometimes called hypervisor. You install it using the following command:
    brew cask install virtualbox
    
    Stay alert your password is required. Done! Nice.

    Installing Vagrant

    Vagrant is an helper installation program that will create for you a complete configured virtualized server. It uses a simple Ruby file as its configuration in order to produce reproducible images of your server. When you want to send a server to your coworkers, you only send this file. When you want to create a new server with some preinstalled tools, you just edit the configuration file. The same step as before is required:
    brew cask install vagrant
    After a required password, you got it now as an available new command.

    Now your system is almost a Cloud controller (well, almost) :)

    Installing and running your server OS of choice

    With your new artillery, you are able to install every virtual machine image. Here, I depict the details for installing an Ubuntu server. Sure, you can choose every other OSes you may like (just Googles it :) ).
    mkdir ~/VirtualBoxes
    cd ~/VirtualBoxes
    vagrant init UbuntuServer
    
    This step create a simple configuration file named Vagrantfile that we will edit. Choose your favorite editor. Mine is Vim and you can turn on the syntax using the nice vim-vagrant plugin (which comes with a supercharge Vagrant command). As the Vagrantfile is a simple Ruby file, you should be able to activate the appropriate syntax highlighting.

    Ready? Just edit the Vagrantfile and replace the line that starts with # config.vm.bow_url = "... with:
      config.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-i386-vagrant-disk1.box"
    
    That's all. Your server is running. Note that the installation is only done once :)

    Check you virtual server

    Launch VirtualBox in your Launcher and you can see it running.
    My screenshot is in french but you should see where we get.

    Turning off the server

    Still in your command line? Vagrant helps you out also in this field:
    vagrant halt