aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst12
-rw-r--r--docs/conf.py1
-rw-r--r--docs/functionality.rst32
-rw-r--r--docs/index.rst3
-rw-r--r--docs/installation.rst2
-rw-r--r--docs/schemas.rst19
-rw-r--r--requirements.pip.dev.txt (renamed from requirements.pip.txt)0
-rw-r--r--requirements.pip.doc.txt1
-rw-r--r--requirements.pip.run.txt5
-rw-r--r--schemas_json/project.yaml185
-rw-r--r--src_py/hatter/executor.py29
11 files changed, 179 insertions, 110 deletions
diff --git a/README.rst b/README.rst
index 533ade8..015e8a7 100644
--- a/README.rst
+++ b/README.rst
@@ -18,8 +18,9 @@ Runtime requirements
--------------------
* python >=3.6
+* libvirt
-Additional required python packages are listed in `requirements.pip.txt`.
+Additional required python packages are listed in `requirements.pip.run.txt`.
Development requirements
@@ -28,20 +29,22 @@ Development requirements
* nodejs >=7
* yarn
+Additional required python packages are listed in `requirements.pip.dev.txt`.
+
Documentation
-------------
-Online documentation available at `http://hatter.readthedocs.io`.
+Online documentation available at `<http://hatter.readthedocs.io>`_.
Build
-----
-Build tool used for Hatter is pydoit (`http://pydoit.org/`). It can be
+Build tool used for Hatter is pydoit (`<http://pydoit.org>`_). It can be
installed together with other python dependencies by running::
- $ pip install -r requirements.pip.txt
+ $ pip install -r requirements.pip.dev.txt
For listing available doit tasks, use::
@@ -71,6 +74,5 @@ TODO
* other
- * documentation
* write complete setup.py
* distribution
diff --git a/docs/conf.py b/docs/conf.py
index 1d6265f..bc23583 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -7,6 +7,7 @@ extensions = ['sphinx.ext.imgmath',
project = 'Hatter'
version = '0.0.1'
+copyright = '2017, Božo Kopić'
master_doc = 'index'
html_theme = 'sphinx_rtd_theme'
diff --git a/docs/functionality.rst b/docs/functionality.rst
new file mode 100644
index 0000000..6943f14
--- /dev/null
+++ b/docs/functionality.rst
@@ -0,0 +1,32 @@
+Functionality
+=============
+
+Hatter is CI tool with emphasis on simple workflow based on virtual machine
+work executors. In contrast to most other CI tools, Hatter doesn't have
+specialized executors that need to be installed on machines that execute
+user defined commands. Each executor is generic VM with SSH daemon which
+is used for file transfer and execution of user defined commands. Therefore,
+Hatter is implemented as single daemon that orchestrates VMs lifecycle and
+remote command execution.
+
+
+Server
+------
+
+Hatter server daemon provides project execution orchestrator facility with
+web-based administration interface. It is configured with single YAML
+configuration defined by :ref:`JSON Schema <server-configuration>`. Single
+server instance can support automation of multiple projects.
+
+
+Project
+-------
+
+Hatter project is represented by single git repository containing project
+configuration file - `.hatter.yml`. Configuration file is defined by
+:ref:`JSON Schema <project-configuration>`. This configuration can define
+multiple execution environments with appropriate execution commands.
+
+
+Execution environment
+---------------------
diff --git a/docs/index.rst b/docs/index.rst
index df3c1d3..3ae48eb 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -5,3 +5,6 @@ Content
:includehidden:
introduction
+ functionality
+ installation
+ schemas
diff --git a/docs/installation.rst b/docs/installation.rst
new file mode 100644
index 0000000..11e4437
--- /dev/null
+++ b/docs/installation.rst
@@ -0,0 +1,2 @@
+Installation
+============
diff --git a/docs/schemas.rst b/docs/schemas.rst
new file mode 100644
index 0000000..4425ce3
--- /dev/null
+++ b/docs/schemas.rst
@@ -0,0 +1,19 @@
+JSON Schemas
+============
+
+.. _project-configuration:
+
+Project configuration
+---------------------
+
+.. literalinclude:: ../schemas_json/project.yaml
+
+
+.. _server-configuration:
+
+Server configuration
+--------------------
+
+.. literalinclude:: ../schemas_json/server.yaml
+
+.. literalinclude:: ../schemas_json/logging.yaml
diff --git a/requirements.pip.txt b/requirements.pip.dev.txt
index 764e73e..764e73e 100644
--- a/requirements.pip.txt
+++ b/requirements.pip.dev.txt
diff --git a/requirements.pip.doc.txt b/requirements.pip.doc.txt
new file mode 100644
index 0000000..6966869
--- /dev/null
+++ b/requirements.pip.doc.txt
@@ -0,0 +1 @@
+sphinx
diff --git a/requirements.pip.run.txt b/requirements.pip.run.txt
new file mode 100644
index 0000000..2471761
--- /dev/null
+++ b/requirements.pip.run.txt
@@ -0,0 +1,5 @@
+aiohttp
+libvirt-python
+pyyaml
+paramiko
+setuptools
diff --git a/schemas_json/project.yaml b/schemas_json/project.yaml
index cb3506b..7a66914 100644
--- a/schemas_json/project.yaml
+++ b/schemas_json/project.yaml
@@ -3,97 +3,100 @@
id: "hatter://project.yaml#"
title: Project
description: Project configuration
-type: object
-required:
- - vm
- - ssh
- - script
-properties:
- vm:
- title: VM
- description: VM configuration
- type: object
- required:
- - domain
- properties:
- uri:
- title: URI
- description: Libvirt URI
- type: string
- default: "qemu:///system"
- domain:
- title: Domain
- description: |
- Domain registered with libvirt used as execution
- environment
- type: string
- snapshot:
- title: Snapshot
- description: |
- Snapshot used as initial execution environment state
- type: string
- temp_snapshot:
- title: Temporary snapshot
- description: |
- Snapshot used for storing initial domain state
- type: string
- default: temp_hatter
- get_address_retry_count:
- title: Get address retry count
- description: |
- Maximum number of retries for obtaining running VM guest
- IP address
- type: integer
- default: 10
- get_address_delay:
- title: Get address delay
+type: array
+items:
+ type: object
+ description: Single execution environment
+ required:
+ - vm
+ - ssh
+ - script
+ properties:
+ vm:
+ title: VM
+ description: VM configuration
+ type: object
+ required:
+ - domain
+ properties:
+ uri:
+ title: URI
+ description: Libvirt URI
+ type: string
+ default: "qemu:///system"
+ domain:
+ title: Domain
+ description: |
+ Domain registered with libvirt used as execution
+ environment
+ type: string
+ snapshot:
+ title: Snapshot
+ description: |
+ Snapshot used as initial execution environment state
+ type: string
+ temp_snapshot:
+ title: Temporary snapshot
+ description: |
+ Snapshot used for storing initial domain state
+ type: string
+ default: temp_hatter
+ get_address_retry_count:
+ title: Get address retry count
+ description: |
+ Maximum number of retries for obtaining running VM guest
+ IP address
+ type: integer
+ default: 10
+ get_address_delay:
+ title: Get address delay
+ description: |
+ Delay in seconds between successive get address requests
+ type: number
+ default: 5
+ ssh:
+ title: SSH
+ description: VM guest SSH daemon configuration
+ type: object
+ required:
+ - username
+ - password
+ properties:
+ username:
+ title: Username
+ description: Username for connecting to VM guest SSH daemon
+ type: string
+ password:
+ title: Password
+ description: Password for connecting to VM guest SSH daemon
+ type: string
+ connect_retry_count:
+ title: Connect retry count
+ description: |
+ Maximum number of connect retries
+ type: integer
+ default: 10
+ connect_delay:
+ title: Connect delay
+ description: |
+ Delay in seconds between successive connect calls
+ type: number
+ default: 5
+ connect_timeout:
+ title: Connect timeout
+ description: |
+ Single connect's TCP connect timeout and authenticate
+ timeout in seconds
+ type: number
+ default: 1
+ script:
+ title: Script
+ description: |
+ List of shell commands executed inside VM guest
+ type: array
+ items:
+ title: Command
description: |
- Delay in seconds between successive get address requests
- type: number
- default: 5
- ssh:
- title: SSH
- description: VM guest SSH daemon configuration
- type: object
- required:
- - username
- - password
- properties:
- username:
- title: Username
- description: Username for connecting to VM guest SSH daemon
+ Single shell command
type: string
- password:
- title: Password
- description: Password for connecting to VM guest SSH daemon
- type: string
- connect_retry_count:
- title: Connect retry count
- description: |
- Maximum number of connect retries
- type: integer
- default: 10
- connect_delay:
- title: Connect delay
- description: |
- Delay in seconds between successive connect calls
- type: number
- default: 5
- connect_timeout:
- title: Connect timeout
- description: |
- Single connect's TCP connect timeout and authenticate
- timeout in seconds
- type: number
- default: 1
- script:
- title: Script
- description: |
- List of shell commands executed inside VM guest
- type: array
- items:
- title: Command
- description: |
- Single shell command
- type: string
...
diff --git a/src_py/hatter/executor.py b/src_py/hatter/executor.py
index 271d60d..2d1ae2a 100644
--- a/src_py/hatter/executor.py
+++ b/src_py/hatter/executor.py
@@ -23,20 +23,21 @@ def run(log, repo_path, commit='HEAD', archive_name='hatter_archive'):
_git_archive(repo_path, commit, archive_path)
log.info('loading project configuration')
conf = _load_conf(archive_path)
- log.info('starting virtual machine')
- with contextlib.closing(_VM(conf['vm'])) as vm:
- log.info('creating SSH connection')
- with contextlib.closing(_SSH(conf['ssh'], vm.address)) as ssh:
- log.info('transfering repository to virtual machine')
- ssh.execute('rm -rf {} {}'.format(archive_file_name,
- archive_name))
- ssh.upload(archive_path, archive_file_name)
- ssh.execute('mkdir {}'.format(archive_name))
- ssh.execute('tar xf {} -C {}'.format(archive_file_name,
- archive_name))
- log.info('executing scripts')
- for script in conf['scripts']:
- ssh.execute(script, archive_name, log)
+ for i in conf:
+ log.info('starting virtual machine')
+ with contextlib.closing(_VM(i['vm'])) as vm:
+ log.info('creating SSH connection')
+ with contextlib.closing(_SSH(i['ssh'], vm.address)) as ssh:
+ log.info('transfering repository to virtual machine')
+ ssh.execute('rm -rf {} {}'.format(archive_file_name,
+ archive_name))
+ ssh.upload(archive_path, archive_file_name)
+ ssh.execute('mkdir {}'.format(archive_name))
+ ssh.execute('tar xf {} -C {}'.format(archive_file_name,
+ archive_name))
+ log.info('executing scripts')
+ for script in i['scripts']:
+ ssh.execute(script, archive_name, log)
t_end = time.monotonic()
log.info('executor finished (duration: {}s)'.format(t_end - t_begin))