Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

org-converge

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

org-converge

  • 0.0.17
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

-- mode: org; mode: auto-fill; --

#+STARTUP: showeverything

  • Org Converge

    [[https://secure.travis-ci.org/wallyqs/org-converge.png?branch=master]]

** Description

A framework to create documented reproducible runs using [[http://orgmode.org/worg/org-contrib/babel/Org Babel][Org Mode]], borrowing several ideas of what is possible to do with tools like =chef-solo=, =rake=, =foreman= and =capistrano=.

** Install

: gem install org-converge

** Motivation

[[http://orgmode.org/worg/org-contrib/babel/Org Babel][Org Mode]] has proven to be flexible enough to write [[http://www.jstatsoft.org/v46/i03][reproducible research papers]], then I believe that configuring and setting up a server for example, is something that could also be done using the same approach, given that /converging/ the configuration is a kind of run that one ought to be able to reproduce.

Taking the original Emacs implementation as reference, Org Converge uses the [[https://github.com/wallyqs/org-ruby][Ruby implementation of the Org mode parser]] to implement and enhance the functionality from Org Babel by adding helpers to define the properties of a run while taking advantage of what is already there in the Ruby ecosystem.

** Usage examples

Org Converge supports the following kind of runs below:

*** Parallel runs

Each one of the code blocks is run on an independent process.
This is akin to having a =Procfile= based application, where
one of the runner command would be to start a web application
and the other one to start the a worker processes.

In the following example, we are defining 2 code blocks, one 
that would be run using Ruby and one more that would be run in Python.
Notice that the Python block has =:procs= set to 2, meaning that 
it would spawn 2 processes for this.

#+begin_src sh ,#+TITLE: Sample parallel run   ,#+name: infinite-worker-in-ruby ,#+begin_src ruby $stdout.sync = true loop { puts "working!"; sleep 1; } ,#+end_src   ,#+name: infinite-worker-in-python ,#+begin_src python :procs 2 import sys import time

while True: print "working too" sys.stdout.flush() time.sleep(1) ,#+end_src #+end_src

The above example can be run with the following:

: org-run procfile-example.org

Sample output of the run:

#+begin_src sh [2014-06-07T18:05:48 +0900] infinite-worker-in-ruby -- started with pid 19648 [2014-06-07T18:05:48 +0900] infinite-worker-in-python:1 -- started with pid 19649 [2014-06-07T18:05:48 +0900] infinite-worker-in-python:2 -- started with pid 19650 [2014-06-07T18:05:48 +0900] infinite-worker-in-python:1 -- working too [2014-06-07T18:05:48 +0900] infinite-worker-in-python:2 -- working too [2014-06-07T18:05:48 +0900] infinite-worker-in-ruby -- working! [2014-06-07T18:05:49 +0900] infinite-worker-in-python:1 -- working too [2014-06-07T18:05:49 +0900] infinite-worker-in-python:2 -- working too #+end_src

*** Sequential runs

In case the code blocks form part of a runlist that should be 
ran sequentially, it is possible to do this by specifying the
~runmode=sequential~ option.

#+begin_src sh ,#+TITLE: Sample sequential run ,#+runmode: sequential   ,#+name: first ,#+begin_src sh echo "first" ,#+end_src   ,#+name: second ,#+begin_src sh echo "second" ,#+end_src   ,#+name: third ,#+begin_src sh echo "third" ,#+end_src   ,#+name: fourth ,#+begin_src sh echo "fourth" ,#+end_src #+end_src

In order to specify that this is to be run sequentially, we set the runmode option in the command line:

: org-run runlist-example.org --runmode=sequential

Another way of specifying this is via the Org mode file itself:

#+begin_src org ,#+TITLE: Defining the runmode as an in buffer setting ,#+runmode: sequential #+end_src

Sample output:

#+begin_src sh [2014-06-07T18:10:33 +0900] first -- started with pid 19845 [2014-06-07T18:10:33 +0900] first -- first [2014-06-07T18:10:33 +0900] first -- exited with code 0 [2014-06-07T18:10:33 +0900] second -- started with pid 19846 [2014-06-07T18:10:33 +0900] second -- second [2014-06-07T18:10:33 +0900] second -- exited with code 0 [2014-06-07T18:10:33 +0900] third -- started with pid 19847 [2014-06-07T18:10:33 +0900] third -- third [2014-06-07T18:10:33 +0900] third -- exited with code 0 [2014-06-07T18:10:33 +0900] fourth -- started with pid 19848 [2014-06-07T18:10:33 +0900] fourth -- fourth [2014-06-07T18:10:33 +0900] fourth -- exited with code 0 #+end_src

*** Configuration management runs

For example, using Org Babel tangling functionality we can spread
config files on a server by writing the following on a ~server.org~ file...

#+begin_src sh   Configuration for a component that shoul be run in multitenant mode:   ,#+begin_src yaml :tangle /etc/component.yml multitenant: false status_port: 10004 ,#+end_src #+end_src

Then run:

: sudo org-tangle server.org

Note: The above tangle command is a reimplementation of the tangling functionality from Org mode using Ruby. If you are interested in tangling from the command line without losing functionality and have available a local Emacs Org mode install, the following project can be useful: https://github.com/ngirard/org-noweb

*** Idempotent runs

A run can have idempotency checks (similar to how the execute resource from [[http://docs.opscode.com/resource_execute.html][Chef]] works).

An example of this, would be when installing packages.  In this example,
we want to install the =build-essential= package once, and skip it in following runs:

#+begin_src sh ,** Installing the dependencies   Need the following so that bundle install can compile the native extensions correctly.    ,#+name: build-essential-installed ,#+begin_src sh dpkg -l | grep build-essential ,#+end_src     ,#+name: build_essentials ,#+begin_src sh :unless build-essential-installed apt-get install build-essential -y ,#+end_src    ,#+name: bundle_install ,#+begin_src sh cd project_path bundle install ,#+end_src #+end_src

Furthermore,since we are using Org mode syntax, it is possible to reuse this setup file by including it into another Org file:

#+begin_src sh ,#+TITLE: Another setup   Include the code blocks from the server into this:    ,#+include: "server.org"   ,#+name: install_org_mode ,#+begin_src sh apt-get install org-mode -y ,#+end_src #+end_src #+end_src

Since this a run that involves converging into a state, it would be run sequentially with idempotency checks applied:

: sudo org-converge setup.org

*** Dependencies based runs

In this type of runs we use the =:after= and =:before=
header arguments to specify the prerequisites for a code block to run,
similar to some of the functioality provided by tools like =rake= 
(Behind the scenes, these arguments create =Rake= tasks)

In order for this kind of run to work, it has to be specified
what is the task that we are converging to by using 
the =#+final_task:= in buffer setting:

#+begin_src sh ,#+TITLE: Linked tasks example ,#+runmode: tasks ,#+final_task: final   ,#+name: second ,#+begin_src sh :after first for i in seq 5 10; do echo $i >> out.log done ,#+end_src   ,#+name: first ,#+begin_src ruby 5.times { |n| File.open("out.log", "a") {|f| f.puts n } } ,#+end_src   ,#+name: final ,#+begin_src python :after second :results output print "Wrapping up with Python in the end" f = open('out.log', 'a') f.write('11') f.close() ,#+end_src   ,#+name: prologue ,#+begin_src sh :before first :results output echo "init" > out.log ,#+end_src #+end_src

: org-run chained-example.org --runmode=chained

Instead of using =--runmode= options, it is also possible to just declare in buffer
that the Org file should be run chained mode.

#+begin_src org
,#+TITLE:   Defining the runmode as an in buffer setting 
,#+runmode: chained
#+end_src

Sample output:

#+begin_src sh [2014-06-07T18:14:25 +0900] Running final task: final [2014-06-07T18:14:25 +0900] prologue -- started with pid 20035 [2014-06-07T18:14:25 +0900] prologue -- exited with code 0 [2014-06-07T18:14:25 +0900] first -- started with pid 20036 [2014-06-07T18:14:26 +0900] first -- exited with code 0 [2014-06-07T18:14:26 +0900] second -- started with pid 20038 [2014-06-07T18:14:26 +0900] second -- exited with code 0 [2014-06-07T18:14:26 +0900] final -- started with pid 20040 [2014-06-07T18:14:26 +0900] final -- Wrapping up with Python in the end [2014-06-07T18:14:26 +0900] final -- exited with code 0 #+end_src

*** Remote runs

For any of the cases above, it is also possible to specify
whether the code blocks should be run remotely on another node.
This is done by using =:dir= in the code block header argument.

#+begin_src sh ,#+sshidentityfile: vagrant/keys/vagrant ,#+name: remote-bash-code-block   ,#+begin_src sh :results output :dir /vagrant@127.0.0.1#2222:/tmp random_number=$RANDOM for i in seq 1 10; do echo "[$random_number] Running script is $0 being run from pwd"; done ,#+end_src #+end_src

Note that in order for the above to work, it is also needed to set identity to be used by ssh.

*** Asserted runs

In case the Org mode file has a results block which represents the expected result, 
there is an ~org-spec~ command which can be useful to check whether there was a change
that no longer makes the results from the Org file valid. Example:

#+begin_src sh ,#+TITLE: Expected results example    ,#+name: hello ,#+begin_src ruby :results output 10.times do puts "hola" end ,#+end_src    ,#+RESULTS: hello ,#+begin_example hola hola hola hola hola hola hola hola hola hola ,#+end_example #+end_src

We can be able to verify whether this is still correct by running:

: org-spec test.org

#+begin_src sh Checking results from 'hello' code block: OK #+end_src

As an example, let's say that the behavior of the original code block changed, and now says hello 5 times instead. In that case the output would be as follows:

#+begin_src diff Checking results from 'hello' code block: DIFF @@ -1,11 +1,6 @@ -hola -hola -hola -hola -hola -hola -hola -hola -hola -hola +hello +hello +hello +hello +hello #+end_src

** Contributing

The project is still in very early development and a proof of concept at this moment. But if you feel that it is interesting enough, please create a ticket to start the discussion.

FAQs

Package last updated on 11 Jun 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc