Skip to content

Commit

Permalink
Merge branch 'rc/0.4.0' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
carsongee committed Jan 4, 2015
2 parents 82f2c6d + 4ed1d10 commit ed2a17d
Show file tree
Hide file tree
Showing 54 changed files with 1,072 additions and 145 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -54,4 +54,4 @@ docs/_build/
target/

# Ignore htpasswd files
.htpasswd
archelond/.htpasswd
10 changes: 5 additions & 5 deletions README.rst
@@ -1,6 +1,9 @@
Archelon
========

.. image:: docs/_static/images/full-logo.png
:align: center

I live more than half my waking life in a shell, and one of my
frustrations has always been having a nicely searchable and synced
shell history across hundreds of servers. This is my attempt at
Expand All @@ -9,8 +12,5 @@ simple API and Web server backed by a nice search engine
(Elasticsearch).

The project is split in two, and the client is actually pretty cool
without the Web server. To get started, check out each of the
respective project's README's.

- `Archelon Client <archelonc/README.rst>`_
- `Archelon Daemon <archelond/README.rst>`_
without the Web server. To get started, check out the
`documentation <http://archelon.rtfd.org/>`_.
2 changes: 1 addition & 1 deletion archelonc/archelonc/__init__.py
Expand Up @@ -3,4 +3,4 @@
Client for Web enabled shell history
"""

VERSION = '0.3.1'
VERSION = '0.4.0'
33 changes: 22 additions & 11 deletions archelond/README.rst
Expand Up @@ -37,8 +37,16 @@ Which will fire up the debug/development server using an in memory
bash history data store that is very forgetful. Once it is up, you
should be able to go `http://localhost:8580/
<http://localhost:8580/>`_, login with the username and password you
created in your htpasswd file, and see a lovely welcome page. To
check out the sample commands you can go to
created in your htpasswd file, and see a lovely Web interface for
searching and deleting your shell history similar to:

.. image:: _static/images/archelond_screen.png
:align: center

. It also provides a simple
button to reveal the token you need in archelonc to connect the two
together. To access the RESTful API side directly, you can check out
the sample commands by visiting
`http://localhost:8580/api/v1/history
<http://localhost:8580/api/v1/history>`_ or get your token for use
with archelonc `http://localhost:8580/api/v1/token
Expand All @@ -59,8 +67,8 @@ storage provider class with something like:
export ARCHELOND_ELASTICSEARCH_INDEX='history'
export ARCHELOND_DATABASE='ElasticData'
The index can be changed, but is the index in elasticsearch that will
be used to store the history.
The index can be changed as desired, but it is the index in
elasticsearch that will be used to store the history.

.. note::

Expand All @@ -70,10 +78,10 @@ be used to store the history.
Running in Production
---------------------

Running the ``archelond`` is good for testing out, but to run it in
production you will want to run it through a proper wsgi application
server. As an example, we've added uwsgi in the requirements and it
can be run in production with something like:
Running the ``archelond`` command is good for testing out, but to run
it in production you will want to run it through a proper wsgi
application server. As an example, we've added uwsgi in the
requirements and it can be run in production with something like:

.. code-block:: bash
Expand All @@ -84,15 +92,18 @@ further secure your shell history.

Running in Heroku
~~~~~~~~~~~~~~~~~
For heroku, it is very easy to setup the application part. Just create a requirements.txt file in the root of your repo with at least one line:

.. code-block::
For heroku, it is very easy to setup the application part. Just
create a requirements.txt file in the root of your repo with at least
one line:

.. code-block:: text
archelond
Setup a Procfile with:

.. code-block::
.. code-block:: text
web: uwsgi uwsgi.ini
Expand Down
2 changes: 1 addition & 1 deletion archelond/archelond/__init__.py
Expand Up @@ -2,4 +2,4 @@
Flask Web server for archelon
"""

VERSION = '0.3.1'
VERSION = '0.4.0'
12 changes: 12 additions & 0 deletions archelond/archelond/data/__init__.py
@@ -0,0 +1,12 @@
"""
Import all known data store implementations
"""

from archelond.data.elastic import ElasticData
from archelond.data.memory import MemoryData

ORDER_TYPES = [
'r', # reverse
]

__all__ = ['ElasticData', 'MemoryData']
122 changes: 122 additions & 0 deletions archelond/archelond/data/abstract.py
@@ -0,0 +1,122 @@
"""
Abstract base class for data stores
"""
from abc import ABCMeta, abstractmethod


class HistoryData(object):
"""Abstract Data storage for command history
Abstract class implementation of a database for use with command
history. Generally a command data item needs just two things, an
ID and the command itself. It also needs order. See the
:py:class:`archelond.data.MemoryData` class as the simplest
structure using an :py:class:`collections.OrderedDict`.
An ID can be any string, and the concrete implementation of
:py:class:`HistoryData` is responsible for type casting it if
needed.
It is also required implicitly that there is only one entry
per command. Thus ``add`` ing the same command multiple times
should result in the return of just one command when filtered
by a term equal to that command.
"""
__metaclass__ = ABCMeta

@abstractmethod
def __init__(self, config):
"""Setup and configuration of data storage.
Any connections and configuration of the data store should be
done here. It receives the full flask configuration
dictionary.
Args:
config (dict): The flask application configuration
dictionary.
"""
self.config = config

@abstractmethod
def add(self, command, username, host, **kwargs):
"""Add or update a command
Save (update or create) a command to the data store.
Args:
command (str): The command to store
username (str): The username of the person adding it
host (str): The IP address of API caller
Returns:
Command ID (str): The id of the command stored
"""
pass

@abstractmethod
def delete(self, command_id, username, host, **kwargs):
"""Delete a command
Remove a command from the data store, raise a KeyError
if it is not available to be deleted.
Args:
command_id (str): Unique command identifier
username (str): The username of the person adding it
host (str): The IP address of API caller
"""
pass

@abstractmethod
def get(self, command_id, username, host, **kwargs):
"""Get a single command
Retrieve a single command by username and id. Raise a
KeyError if the command does not exist.
Args:
command_id (str): Unique command identifier
username (str): The username of the person adding it
host (str): The IP address of API caller
Returns:
Command (dict): Dictionary with at least the keys ``id`` and ``command``
"""
pass

@abstractmethod
def all(self, order, username, host, **kwargs):
"""Unfiltered but ordered command history
Return the full data set as a list of dict structures
in the specified order.
Args:
order (str): An ordering from :py:const:`ORDER_TYPES`
username (str): The username of the person adding it
host (str): The IP address of API caller
Returns:
list: A list of dictionaries where each dictionary must
have at least a ``command`` key and an ``id`` key.
"""
pass

@abstractmethod
def filter(self, term, order, username, host, **kwargs):
"""Get a filtered by term and ordered command history
Args:
term (str): The term being searched for/filtered by.
order (str): An ordering from :py:const:`ORDER_TYPES`
username (str): The username of the person adding it
host (str): The IP address of API caller
Returns:
list: A list of dictionaries where each dictionary must
have at least a ``command`` key and an ``id`` key.
"""
pass

0 comments on commit ed2a17d

Please sign in to comment.