Re: Parallel SSH and system monitoring in Clojure

2012-03-22 Thread Damon Snyder
Hi Chris,
Cool. Thanks for sharing with the group. I also worked on something
similar: https://github.com/drsnyder/gantry. I was getting frustrated
with our current Frankenstein version of capistrano and wanted to
tinker with building a basic remote execution and deployment tool
using clojure.

Damon

On Mar 15, 2:12 pm, Chris McBride cmm7...@gmail.com wrote:
 Hi,

    I releases two simple clojure libraries to help running commands
 via SSH on multiple servers. Hopefully someone will find it useful.

    http://info.rjmetrics.com/blog/bid/54114/Parallel-SSH-and-system-moni...
    https://github.com/RJMetrics/Parallel-SSH
    https://github.com/RJMetrics/Server-Stats

 Best,
 Chris McBride

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: ANN: Gantry system administration and deploy tool written in clojure

2011-07-09 Thread Damon Snyder
Hi Martin,
Thanks! Under the hood gantry uses rsync for the upload. See
https://github.com/drsnyder/gantry/blob/master/src/gantry/core.clj#L148.

Damon

On Jul 8, 1:30 am, martin_clausen martin.clau...@gmail.com wrote:
 Looks very nice. You should consider supporting rsync for the upload
 command.

 On Jul 6, 10:36 pm, Damon Snyder drsny...@gmail.com wrote:







  Hello,
  I wanted to let everyone know about a tool I have been working on. I'm
  calling it gantry (a type of crane that I see every day on my commute
  on BART to SF and inspired by crane). I started working on it after
  seeing crane (https://github.com/getwoven/crane) and seeing the
  possibilities while also suffering the frustration of using capistrano
  for deployment of a few non-rails apps (PHP to be specific). I was
  longing for something simpler and found fabric (http://fabfile.org)
  but I was disappointed when I learned that all commands are executed
  sequentially (this has since been fixed I believe). I also wanted to
  spend more time with clojure and see how it could be used for system
  administration and scripting.

  Gantry comes in two parts. The first is a command line tool and task
  macro. You define tasks and the commands specified in those tasks
  (provided by gantry.run) are run in parallel on each host using agents/
  send-off. Here is a quick start:

  $ curl -Lhttps://github.com/downloads/drsnyder/gantry/gantry
  gantry; chmod +x gantry

  $ cat  gantryfile
  (use 'gantry.run)
  (task hello
     (run (format echo \hello %s at $(hostname)\ (:name (get-args
  (get-config))
  ^D

  $ ./gantry -H one.myhost.com,two.myhost.com -t hello -s name=bob
  INFO [one.myhost.com] hello bob at one.myhost.com
  INFO [two.myhost.com] hello bob at two.myhost.com

  The second part is a library for running commands remotely on one or
  more hosts. Here are some examples:

  (use 'gantry.run)

  (remote host.com yum install -y atop)
  (remote host.com yum install -y atop {:user deployer})

  (remote* [host.com, host2.com] yum install -y atop {:user
  deployer})

  (upload host.com filea /tmp)
  (upload host.com [filea, fileb] /tmp {:port 222})

  (upload* [host.com, host2.com] [filea, fileb] /tmp {:id /
  home/deployer/my-key})

  The jar is in clojars. Use [gantry 0.0.1-SNAPSHOT] in your
  dependencies. Seehttps://github.com/drsnyder/gantryforthe
  documentation and source.

  Feedback welcome!

  Damon

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


ANN: Gantry system administration and deploy tool written in clojure

2011-07-06 Thread Damon Snyder
Hello,
I wanted to let everyone know about a tool I have been working on. I'm
calling it gantry (a type of crane that I see every day on my commute
on BART to SF and inspired by crane). I started working on it after
seeing crane (https://github.com/getwoven/crane) and seeing the
possibilities while also suffering the frustration of using capistrano
for deployment of a few non-rails apps (PHP to be specific). I was
longing for something simpler and found fabric (http://fabfile.org)
but I was disappointed when I learned that all commands are executed
sequentially (this has since been fixed I believe). I also wanted to
spend more time with clojure and see how it could be used for system
administration and scripting.

Gantry comes in two parts. The first is a command line tool and task
macro. You define tasks and the commands specified in those tasks
(provided by gantry.run) are run in parallel on each host using agents/
send-off. Here is a quick start:

$ curl -L https://github.com/downloads/drsnyder/gantry/gantry 
gantry; chmod +x gantry

$ cat  gantryfile
(use 'gantry.run)
(task hello
   (run (format echo \hello %s at $(hostname)\ (:name (get-args
(get-config))
^D

$ ./gantry -H one.myhost.com,two.myhost.com -t hello -s name=bob
INFO [one.myhost.com] hello bob at one.myhost.com
INFO [two.myhost.com] hello bob at two.myhost.com

The second part is a library for running commands remotely on one or
more hosts. Here are some examples:

(use 'gantry.run)

(remote host.com yum install -y atop)
(remote host.com yum install -y atop {:user deployer})

(remote* [host.com, host2.com] yum install -y atop {:user
deployer})

(upload host.com filea /tmp)
(upload host.com [filea, fileb] /tmp {:port 222})

(upload* [host.com, host2.com] [filea, fileb] /tmp {:id /
home/deployer/my-key})

The jar is in clojars. Use [gantry 0.0.1-SNAPSHOT] in your
dependencies. See https://github.com/drsnyder/gantry for the
documentation and source.

Feedback welcome!

Damon

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Best practice for distributing a standalone clojure command line utility

2011-06-17 Thread Damon Snyder
Hi Miki,
Thats an interesting idea that I had not thought of. It nicely
encapsulates everything in one package.

Thanks!
Damon

On Jun 16, 6:15 pm, Miki miki.teb...@gmail.com wrote:
 One more option is to embed the jar in base64 encoding in a script, extract
 the jar to a temp location and run it.
 The following Perl script does that (it uses the base64 executable, but you
 can probably use MIME::Base64 as well).
  #!/usr/bin/env perl

 $jar = /tmp/lp-$ENV{USER}.jar;
 unless (-e $jar) {
     open DECODE, |base64 -d  $jar or die can't open base64 pipe;
     print DECODE DATA;}

 exec java, -jar, $jar, @ARGV

 __DATA__
 YOUR BASE64 ENCODED JAR GOES HERE

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Best practice for distributing a standalone clojure command line utility

2011-06-16 Thread Damon Snyder
Hi Everyone,
I'm have a side project that I'm working on that I want to distribute
as a standalone script. This is probably best illustrated as an
example. What I would like to be able to do is give users a script, so
they can do:

   gantry -H example.host.com -f examples/tasks.clj uptime

Instead of

   java -jar gantry-0.0.1-SNAPSHOT-standalone.jar -H example.host.com -
f examples/tasks.clj uptime

What I'm curious about is what is the best practice within the
community for doing this? Backing up for a minute, to me, the first
invokation would be the preferred in my mind. Perhaps the second isn't
so bad if you are used to interacting with jar files in this way. I
think I would prefer that the details of running java be abstracted
away from the command line user's experience.

A few approaches I have thought about: 1) Upload the stand alone jar
to github and have the gantry script pull down the standalone into
~/.gantry and construct the command line. 2) Create a cake wrapper
(not preferred because it introduces a dependency). 3) Forget the
wrapper and just distribute the jar.

The project I am talking about is here: https://github.com/drsnyder/gantry.
Thanks,
Damon

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Properly including clojure-contrib

2011-06-16 Thread Damon Snyder
Hi cmn,
I think if you add clojure.contrib.string to your use or simply add
(:use clojure.contrib.string). I think that should fix it.

Damon

On Jun 16, 12:16 pm, octopusgrabbus octopusgrab...@gmail.com wrote:
 What is the proper way to :use clojure contrib so split resolves as a
 symbol?

 ns test-csv
   (:gen-class)
   (:import (java.io BufferedReader FileReader StringReader))
   (:use clojure-csv.core)
   (:use [clojure.contrib.def]))

 (defn process-file [file-name]
     (with-open [br (BufferedReader. (FileReader. file-name))]
                             (println (split , (line-seq br)

 (defn -main [ args]
   (process-file resultset.csv))

 Thanks.
 cmn

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question about when to use protocol+record and compilation warnings

2010-12-28 Thread Damon Snyder
Thanks everyone for all of the feedback. I think I have a solution to
the warnings and if I understand deftype/defrecord, I should be able
to replace defrecord with deftype in my implementation. I'll give it a
try and report back when I have a chance.

Thanks,
Damon

On Dec 26, 7:31 pm, David Nolen dnolen.li...@gmail.com wrote:
 On Sun, Dec 26, 2010 at 9:00 PM, Ken Wesson kwess...@gmail.com wrote:
  On Sun, Dec 26, 2010 at 9:25 PM, Alex Osborne a...@meshy.org wrote:
   Ken Wesson kwess...@gmail.com writes:

   Actually you don't need to AOT compile records or types. They work fine
   for interactive development.

   Eh. That's not what I saw written elsewhere. Or is it just protocols?
   Though usually those are used hand-in-hand with records.

   Perhaps you're thinking of gen-class?

  No.

   Protocols are also fine for interactive development.

  Someone here definitely said, recently and specifically, that at least
  one of the feature-complex around deftype/defprotocol/defrecord
  required AOT compilation.

 definterface/deftype/defprotocol/et al do not require AOT. structmaps are a
 legacy feature. defrecord is the way to go now.

 I've encountered some odd behavior at the SLIME REPL on occasion, but I
 haven't yet pinpointed a specific flow to recreate. It wasn't serious enough
 to impede interactive development.

 David

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question about when to use protocol+record and compilation warnings

2010-12-28 Thread Damon Snyder
This worked as expected. I just replaced defrecord with deftype here
https://github.com/drsnyder/beanstalk/blob/82f301f1f825bb05aa14d85a220ec57c1dea61b2/src/beanstalk/core.clj#L117
and re-ran my tests.

The suggestion from Baishampayan to add (:refer-clojure :exclude [read
peek use]) also worked. I added this to the core.clj and the tests and
there are no warnings.

Thanks!

Damon

On Dec 28, 9:45 pm, Damon Snyder drsny...@gmail.com wrote:
 Thanks everyone for all of the feedback. I think I have a solution to
 the warnings and if I understand deftype/defrecord, I should be able
 to replace defrecord with deftype in my implementation. I'll give it a
 try and report back when I have a chance.

 Thanks,
 Damon

 On Dec 26, 7:31 pm, David Nolen dnolen.li...@gmail.com wrote:







  On Sun, Dec 26, 2010 at 9:00 PM, Ken Wesson kwess...@gmail.com wrote:
   On Sun, Dec 26, 2010 at 9:25 PM, Alex Osborne a...@meshy.org wrote:
Ken Wesson kwess...@gmail.com writes:

Actually you don't need to AOT compile records or types. They work 
fine
for interactive development.

Eh. That's not what I saw written elsewhere. Or is it just protocols?
Though usually those are used hand-in-hand with records.

Perhaps you're thinking of gen-class?

   No.

Protocols are also fine for interactive development.

   Someone here definitely said, recently and specifically, that at least
   one of the feature-complex around deftype/defprotocol/defrecord
   required AOT compilation.

  definterface/deftype/defprotocol/et al do not require AOT. structmaps are a
  legacy feature. defrecord is the way to go now.

  I've encountered some odd behavior at the SLIME REPL on occasion, but I
  haven't yet pinpointed a specific flow to recreate. It wasn't serious enough
  to impede interactive development.

  David

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Question about when to use protocol+record and compilation warnings

2010-12-26 Thread Damon Snyder
Hello,
In an effort to learn a little more about clojure (and possibly
introduce it at work) I decided to write a native client for the
Beanstalk work queue. See http://kr.github.com/beanstalkd/ for more
information about the queue and https://github.com/drsnyder/beanstalk
for the client.

One of the decisions I wasn't sure about was whether to use a protocol
or a struct map for the (socket, reader, writer) tuple. I started
using a struct-map and then switched over to defprotocol/defrecord.
See 
https://github.com/drsnyder/beanstalk/blob/82f301f1f825bb05aa14d85a220ec57c1dea61b2/src/beanstalk/core.clj#L117
for the definition.

Is one preferred over the other (struct vs record)? Using the protocol
+record idiom maps really well to the queue protocol-- you end up with
statements like (.put object params), (.reserve object) etc which are
very clear and intuitive from the developers perspective. It creates a
one-to-one mapping to the beanstalkd protocol commands. If I were
using a struct-map I might have methods like (beanstalk-put object
params) etc.

But one issue I encountered with defprotocol is that there appears to
be a possible symbol table/space issue. When I compile, I get warnings
like the following:

Warning: protocol #'beanstalk.core/BeanstalkObject is overwriting
function read
Warning: protocol #'beanstalk.core/BeanstalkObject is overwriting
function peek
Warning: protocol #'beanstalk.core/BeanstalkObject is overwriting
function use
WARNING: read already refers to: #'clojure.core/read in namespace:
beanstalk.core, being replaced by: #'beanstalk.core/read
WARNING: peek already refers to: #'clojure.core/peek in namespace:
beanstalk.core, being replaced by: #'beanstalk.core/peek
WARNING: use already refers to: #'clojure.core/use in namespace:
beanstalk.core, being replaced by: #'beanstalk.core/use
WARNING: read already refers to: #'clojure.core/read in namespace:
beanstalk.core-test, being replaced by: #'beanstalk.core/read
WARNING: peek already refers to: #'clojure.core/peek in namespace:
beanstalk.core-test, being replaced by: #'beanstalk.core/peek
WARNING: use already refers to: #'clojure.core/use in namespace:
beanstalk.core-test, being replaced by: #'beanstalk.core/use

Is there something I'm can do to prevent these collisions aside from
using a different name for the method?

Thanks,
Damon

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Feedback on idiomatic clojure

2010-08-19 Thread Damon Snyder
Hi Meikel, Nicolas, and Justin,
Thank you for the great feedback! I learned a lot. I was puzzled about
(update-in (update-in)) and after doing that the - operator makes a
lot of sense. The reduce is clever and fits nicely as well.

I dropped the function that read in the lines of the file and used
read-lines instead. Below is what I put together after the feedback.

Thanks,
Damon

PS- I was mistaken before. The first version was taking over a minute.
This version takes about 15s.

(ns clojure.example.anagrams
  (:require clojure.contrib.duck-streams)
  (:gen-class))

(defn str-sort[string]
  (when string
(apply str (sort string


(defn str-to-lower[string]
  (when string
(.toLowerCase string)))


(defn anagram-add[anagrams akey word]
  (if (contains? anagrams akey)
(- anagrams
  (update-in [akey :count] inc)
  (update-in [akey :words] conj word))
(assoc anagrams akey {:count 1 :words [word]})))

(def normalise (comp str-to-lower str-sort))

(defn build-anagrams[words]
  (reduce #(anagram-add %1 (normalise %2) %2) {} words))


(defn print-anagram[v]
  (println (str (:count (second v))   (first v) :  (:words (second
v)

(defn print-anagrams[ana]
(doseq [v ana]
  (print-anagram v)))

(defn anagram-key[elem]
(- (:count (second elem


;(def *words* (f-to-seq /usr/share/dict/web2))
;(def *anagrams* (sort-by anagram-key (build-anagrams *words*)))
;(print-anagrams (take 10 *anagrams*))

(defn -main[file]
  (time (print-anagrams
  (take 10
(sort-by anagram-key
 (build-anagrams
   (clojure.contrib.duck-streams/read-lines
file)))



On Aug 19, 5:41 am, Meikel Brandmeyer m...@kotka.de wrote:
 Hi,

 here my turn. Comments inline. Hope this helps.

 Sincerely
 Meikel

 (defn f-to-seq
   [file]
   (with-open [rdr (java.io.BufferedReader.
                     (java.io.FileReader. file))]
     (doall (line-seq rdr
 ; Yes. doall is required here. Alternatively you can wrap the whole
 thing
 ; in the with-open. Then you can process also larger files without
 keeping
 ; all data in memory. YMMV.

 (defn str-sort
   [string]
   (when string
     (apply str (sort string
 ; One can also skip the when here. Then nil input returns an empty
 string.
 ; Whether that is better depends on the usage of the return value.
 YMMV.
 ; (if (nil? x) x ...) is usually written as (when x ...).

 (defn str-to-lower
   [string]
   (when string
     (.toLowerCase string)))

 (defn anagram-add
   [anagrams akey word]
   (if (contains? anagrams akey)
     (- anagrams
       (update-in [akey :count] inc)
       (update-in [akey :words] conj word))
     (assoc anagrams akey {:count 1 :words [word]})))
 ; I would prefer vectors over lists to store stuff. You get nice
 ; things for free, like O(1) appending, O(1) reverse, O(1) random
 ; access, ...

 (defn word
   [s]
   (first s))
 ; or: (def word first)
 ; not needed for my solution

 (def normalise (comp str-to-lower str-sort))

 (defn build-anagrams
   [words]
   (reduce #(anagram-add %1 (normalise %2) %2) {} words))
 ; Looping with an accumulator, just returning the latter when the
 ; input is exhausted cries for reduce.

 (defn print-anagram
   [v]
   (println (str (:count (second v))   (first v) :  (:words (second
 v)
 ; one could use destructuring to access things.

 (defn print-anagram
   [anagram]
   (let [[normal-form {:keys [count words]}] anagram]
     (println (str count   normal-form :  words

 (defn print-anagrams
   [ana]
   (doseq [v ana]
     (print-anagram v)))
 ; more descriptive names would be good, I guess

 (defn anagram-key
   [elem]
   (- (:count (second elem
 ; the minus should take care of the reverse?

 (def *words* (f-to-seq /usr/share/dict/web2))
 (def *anagrams* (sort-by anagram-key (build-anagrams *words*)))
 (print-anagrams (take 10 *anagrams*))

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en