Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
*.sx32fsl
*.wx64fsl
*.wx32fsl
*.vbin
*~
79 changes: 39 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
# cl-maprcli

## overview
This project is binding for maprcli and REST binding for Common Lisp.
## Overview
This project implements the MapR Control System (MCS) REST API for Common Lisp.

`maprcli` is a tool for the command-line interface (CLI). And MapR provides REST API by making REST requesting programmatically or in a browser. Please refer to http://maprdocs.mapr.com/home/ReferenceGuide/maprcli-REST-API-Syntax.html
`maprcli` is a tool for the command-line interface (CLI). The MapR MCS provides a REST API for language agnostic programming. Please refer to the [MapR Reference Guide](http://maprdocs.mapr.com/home/ReferenceGuide/maprcli-REST-API-Syntax.html) for details.

## install
cl-maprcli can be installed by quicklisp.
## Installing
This project is not in Quicklisp. Start by cloning the repository into a directory known to ASDF or Quicklisp. E.g.

```
git clone https://github.com/incjung/cl-maprcli.git
```
then in repl session
then in repl session `(ql:quickload "cl-maprcli")` or `(asdf:load-system "cl-maprcli")`

## Configuring
MapR/CS (MapR Control System) needs to know the host that MCS is
running on and the login credentials. Those can be set with `set-host` and `set-authentication`. For example:

```
(swank:operate-on-system-for-emacs "cl-maprcli" (quote load-op))
(set-host "https://192.168.2.51:8443/rest")
(set-authentication '("mapr" "mapr")')
```

## usage
To get information from another remote server without setting the host:
```
(volume-info :host "https://192.168.2.51:8443/rest" :path "/")
```
where :host is mcs host.

MapR's `maprcli` syntax is
## Using the MapR Control System
MapR's `maprcli` shell syntax is:
```
maprcli <command> [<subcommand>...] ?<parameters>
```

For example, if you want to get information about the specified volume, `maprcli` command can be used.
For example, if you want to get information about a particular MapR
volume, `maprcli` command can be used like this from a UNIX shell:

```
maprcli volume info
Expand All @@ -34,31 +46,27 @@ maprcli volume info
[ -columns <column name> ]
```

You must specify either name or path, but not both.
You must specify either name or path, but not both. The CL interface
mirrors this with the `maprcli` function, e.g. `maprcli volume info -path /`

```
maprcli volume info -path /
```

With `cl-maprcli`, You can get same information with
With `cl-maprcli`, you can get same information with `(maprcli
"/volume/info" :path "/")` or `(volume-info :path "/")`. The first
form more closely duplicates the existing command line interface and
might be more familar to existing MapR administrators. The second form
is idiomatic lisp.

Here is another example of two equivalent forms:
```
(maprcli "/volume/info" :path "/")
or
(volume-info :path "/")


(maprcli "volume/create" :path "/test07" :name "helloworld")
or
(volume-create :path "/test07" :name "helloworld") # create volume

(volume-info :path "/test07")
```
and
```
(volume-create :path "/test07" :name "helloworld") ; create volume
```

grammar is
The syntax for commands is:
```
(maprcli "/<command>/<subcommand>" :param-name <param-value>* [:host *host* :output :pretty])
or
(<command>-?<subcommand> :param-name <param-value>* [:host *host* :output :pretty])
```
:host is mcs host
Expand All @@ -72,19 +80,10 @@ or
(PRETTY class-instance) : output
```

To get information from another remote server:
```
(volume-info :host "https://192.168.2.51:8443/rest" :path "/")
```
:host is mcs host. Or You can change host with `set-host` and the authorization id/pw with `set-authorization`

```
(set-host "https://192.168.2.51:8443/rest")
(set-authorization '("mapr" "mapr")')
```

## help page
For example, when you want to knwo "alarm list", then
## Getting Help
You can use the 'help' command to learn more about a command. For
example, when you want to see the alarms for a cluster (i.e. the
"alarm list"), then you can use
```
(help :/alarm/list)
```
1 change: 0 additions & 1 deletion README.txt

This file was deleted.

4 changes: 4 additions & 0 deletions TODO.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* TODO Complete refactoring of authorization -> authentication. We are authenticating, not authorizing here.
* TODO Review exported symbols. Are all of them required? Some look like internal symbols
* TODO Use functions from Alexandria to operate on alists
* TODO Create tests for MapR API. Existing tests do not test any significant functionality
5 changes: 3 additions & 2 deletions cl-maprcli.asd
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
;;;; -*- Mode: LISP; Base: 10; Syntax: ANSI-Common-lisp; Package: CL-USER -*-

(asdf:defsystem "cl-maprcli"
:description "lisp version for MapR maprcli command"
:description "MapR control system API"
:author "Inchul <ijung@mapr.com>"
:license "BSD"
:serial t
:depends-on ("cl-json")
:depends-on ("cl-json"
"drakma")
:in-order-to ((test-op (test-op "cl-maprcli/tests")))
:components ((:file "package")
(:file "cl-maprcli")
Expand Down
20 changes: 9 additions & 11 deletions cl-maprcli.lisp
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
;;;; -*- Mode: LISP; Base: 10; Syntax: ANSI-Common-lisp; Package: CL-MAPRCLI -*-

(in-package "cl-maprcli")
(in-package :cl-maprcli)

(defun make-url-param (alist)
"make a URL parameter format with alist. ex: (make-url-param '((:a . 1) (:b . 2)))"
"Make a URL parameter format with alist. ex: (make-url-param '((:a . 1) (:b . 2)))"
(format nil "~{~a~^&~}" (loop for (a . b) in alist
collect (format nil "~a=~a" a b))))


(defun remove-assoc (item alist)
"remove the item from alist"
"Remove ITEM from ALIST"
(remove-if (lambda (x) (equal (car x) item)) alist))

(defun help (cmd-path)
"return docments about maprcli command. ex: (help :/alaprm/list)"
"Return a documentation string describing a maprcli command. eg: (help :/alarm/list)"
(labels ((get-in (items alist)
(if (endp items) alist
(get-in (rest items)
(cdr (assoc (car items) alist))))))
(get-in (list :paths cmd-path :get :description) (decode-json-from-source #p"./mapr.json"))))

;; http response object
;;; http response object
(defclass mapr-response ()
((status :accessor status :initarg :status )
(data :accessor data :initarg :data :initform '())))

(defmethod set-data ((message mapr-response) obj)
"setter for MAPR-RESPONSE instance"
"Setter for MAPR-RESPONSE instance"
(setf (data message) obj))

(defmethod set-status ((message mapr-response) obj)
"setter for MAPR-RESPONSE instance"
"Setter for status instance"
(setf (status message) obj))

(defmethod pretty ((message mapr-response))
"print formated output"
"Pretty-print output"
(format t "~%~A~%" (status message))
(loop for msg in (data message)
do (format t "~80,,,'=A~%" "")
(loop for (a . b) in msg
do (format t "~35,A : ~A ~%" a b))))


(defun rest-call (host path basic-authorization alist output)
"call http-request with basic authorization and parameters"
"Call http-request with basic authentication and parameters."
(multiple-value-bind (stream code)
(http-request (string-downcase (format nil "~a~a?~a" host path (make-url-param alist))) :basic-authorization basic-authorization :accept "application/json" :content-type "application/json" :want-stream t :method :GET)
(if (equal code 200) (progn (setf (flexi-streams:flexi-stream-external-format stream) :utf-8)
Expand Down
39 changes: 13 additions & 26 deletions mapr-api.lisp
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
;;;; -*- Mode: LISP; Base: 10; Syntax: ANSI-Common-lisp; Package: CL-MAPRCLI -*-

(in-package "cl-maprcli")
(in-package :cl-maprcli)


;; MapR CLI basic Context info
;;; MapR CLI basic context
(defparameter *context* '((:host . "http://localhost:8443/rest")
(:basic-authorization . ("mapr" "mapr"))
(:output . :pretty)))

;; setter/getter context info
;;; setter/getter context info
(defun set-host (host)
"setter for host name. ex: (set-host \"https://192.168.2.51:8443/rest\")"
"Setter for host name. ex: (set-host \"https://192.168.2.51:8443/rest\")"
(let ((ctx (assoc :host *context*)))
(when ctx
(rplacd ctx host))))

(defun set-output-option (option)
"Set default output format"
(let ((ctx (assoc :output *context*)))
(when ctx
(rplacd ctx option))))

(defun set-authorization (auth)
"setter for autorization info. ex: (set-authorization (list \"mapr\" \"mapr\"))"
(defun set-authentication (auth)
"Set cluster authentication credentials. ex: (set-authentication (list \"mapr\" \"mapr\"))"
(let ((ctx (assoc :basic-authorization *context*)))
(when ctx
(rplacd ctx auth))))

(defun list-to-alist (olist)
"convert list to alist."
"Convert list to alist"
(when (and olist (evenp (length olist)))
(cons (cons (car olist) (cadr olist)) (list-to-alist (cddr olist)))))

(defun get-val (item alist)
"getter for alist"
"Getter for alist"
(cdr (assoc item alist)))

(defun make-inputformat-from-user (rest)
"convert user input list into parameter type.
"Convert user input list into parameter type.
ex: (make-inputformat-from-user '(:a 1 :b 2 :host \"abc\" :basic-authorization '(\"m\" \"m\")))"
(let* ((alist (list-to-alist rest))
(output (let ((tmp (get-val :output alist)))
Expand All @@ -56,29 +56,21 @@
(get-val :basic-authorization *context*)))))
(values host basic-authorization alist output)))


(defmacro maprcli (cmd-path &rest rest)
"run maprcli command. ex: (maprcli \"/VOLUME/INFO\" :path \"/\")"
"Run maprcli command. ex: (maprcli \"/VOLUME/INFO\" :path \"/\")"
`(multiple-value-bind (host basic-authorization alist output)
(make-inputformat-from-user ',rest)
(rest-call host ,cmd-path basic-authorization alist output)))

;;(maprcli "/volume/info" :path "/" :output :pretty)
;;(maprcli "/table/region/list" :path "/chatbot.prod/insa_master_002" :output :pretty)


(defmacro maprcli-defs (cmd-path)
"macro for creating maprcli request functions"
"Macro for creating maprcli request functions"
(let ((function-name (intern (string-upcase (subseq (substitute #\- #\/ cmd-path) 1)))))
`(defun ,function-name (&rest rest)
(multiple-value-bind (host basic-authorization alist output)
(make-inputformat-from-user rest)
(rest-call host ,cmd-path basic-authorization alist output)))))

;;(macroexpand-1 '(maprcli-defs "/volume/info"))


;;; making functions for maprcli
;;; Create the MapR API
(maprcli-defs "/ACL/EDIT")
(maprcli-defs "/ACL/SET")
(maprcli-defs "/ACL/SHOW")
Expand Down Expand Up @@ -240,8 +232,3 @@
(maprcli-defs "/VOLUME/SNAPSHOT/REMOVE")
(maprcli-defs "/VOLUME/UNMOUNT")
(maprcli-defs "/VOLUME/UPGRADEFORMAT")


;;(set-host "http://maprdemo:8443/rest")
;;(volume-info :path "/")
;;(volume-list)
Loading