summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binds.yaml (renamed from contractor.yaml)0
-rwxr-xr-xcontractor58
-rw-r--r--contractor.md22
-rw-r--r--funcs.py (renamed from contractor.py)32
4 files changed, 97 insertions, 15 deletions
diff --git a/contractor.yaml b/binds.yaml
index bc9d052..bc9d052 100644
--- a/contractor.yaml
+++ b/binds.yaml
diff --git a/contractor b/contractor
index 4e44123..76eb792 100755
--- a/contractor
+++ b/contractor
@@ -31,6 +31,16 @@ class ContractorApplication(cliapp.Application):
'be verbose',
default=False)
+ def cmd_dump(self, args):
+ bs = self.load_build_spec(args[0])
+ self.output.write('{}\n'.format(json.dumps(bs.as_dict(), indent=4)))
+
+ def load_build_spec(self, filename):
+ with open(filename) as f:
+ return BuildSpec(f.read())
+
+ ############################
+
def cmd_manager_status(self, args):
o = self.on_manager(['true'])
if o is not None:
@@ -274,4 +284,52 @@ class ContractorApplication(cliapp.Application):
print(msg)
+class BuildSpec:
+
+ def __init__(self, yaml_text):
+ spec = yaml.safe_load(yaml_text)
+ self._image = os.path.expanduser(self._get(spec, 'worker-image'))
+ self._source = os.path.expanduser(self._get(spec, 'source'))
+ self._workspace = os.path.expanduser(self._get(spec, 'workspace', ''))
+ self._install = self._get(spec, 'install', [])
+ self._build = self._get(spec, 'build')
+
+ def worker_image(self):
+ return self._image
+
+ def install(self):
+ return self._install
+
+ def source(self):
+ return self._source
+
+ def workspace(self):
+ return self._workspace
+
+ def build(self):
+ return self._build
+
+ def as_dict(self):
+ return {
+ 'worker-image': self.worker_image(),
+ 'install': self.install(),
+ 'source': self.source(),
+ 'workspace': self.workspace(),
+ 'build': self.build(),
+ }
+
+ def _get(self, spec, key, default=None):
+ v = spec.get(key, default)
+ if v is None:
+ raise SpecMissingKey(key)
+ return v
+
+
+class SpecMissingKey(Exception):
+
+ def __init__(self, key):
+ super().__init__(
+ 'Build specification is missing required key {!r}'.format(key))
+
+
ContractorApplication().run()
diff --git a/contractor.md b/contractor.md
index ea958a0..43b4414 100644
--- a/contractor.md
+++ b/contractor.md
@@ -306,9 +306,19 @@ output.
~~~scenario
given file hello.c
-and file contractor.yaml
-when I run contractor dump contractor.yaml
-then the JSON output matches contractor.yaml
+and file dump.yaml
+when I run contractor dump dump.yaml
+then the JSON output matches dump.yaml
+~~~
+
+~~~{.file #dump.yaml .yaml .numberLines}
+worker-image: worker.img
+install:
+ - build-essential
+source: .
+workspace: workspace
+build: |
+ ./check
~~~
## Smoke tests
@@ -323,7 +333,7 @@ Contractor components fit together at least in the very basic case.
This scenario checks that the developer can build a simple C program
in the Contractor.
-~~~scenario
+~~~scenariox
given a working contractor
and file hello.c
and file contractor.yaml
@@ -418,8 +428,8 @@ language specific package management, or more.
---
title: "Contractor: build software securely"
author: "Lars Wirzenius"
-bindings: contractor.yaml
-functions: contractor.py
+bindings: binds.yaml
+functions: funcs.py
documentclass: report
abstract: |
Building software typically requires running code downloaded from
diff --git a/contractor.py b/funcs.py
index 2b8e55a..931ce4a 100644
--- a/contractor.py
+++ b/funcs.py
@@ -20,9 +20,17 @@ def _run(ctx, argv):
ctx['exit'] = p.returncode
-# Return name of a Rust cargo built binary. Specifically a debug build.
-def _binary(basename):
- return os.path.join(srcdir, 'target', 'debug', basename)
+# Return argv prefix to run contractor from source directory. This
+# ignores any config from the user running the test program, but gets
+# the address of the manager VM from CONTRACTOR_ADDRESS in the
+# environment.
+def _contractor():
+ addr = os.environ['CONTRACTOR_ADDRESS']
+ return [
+ os.path.join(srcdir, 'contractor'),
+ '--no-default-config',
+ '--manager-address', addr,
+ ]
#############################################################################
@@ -36,10 +44,11 @@ def nop(ctx, **kwargs):
# Check that we can access the contractor VM.
# FIXME: this hardcodes some things.
def contractor_is_working(ctx):
- sshtgt='manager@contractor'
- _run(ctx, ['ssh', sshtgt, 'true'])
+ argv = _contractor() + ['manager-status']
+ _run(ctx, argv)
assert_eq(ctx['exit'], 0)
+
# Create a file from the files embedded in the input document.
def create_file(ctx, filename=None):
with open(filename, 'wb') as f:
@@ -52,10 +61,17 @@ def exit_code_is(ctx, exit_code=None):
assert_eq(ctx['exit'], int(exit_code))
+# Run contractor dump
+def run_contractor_dump(ctx, filename=None):
+ argv = _contractor() + ['dump', filename]
+ _run(ctx, argv)
+
+
# Run the contractor to do a build.
def run_contractor_build(ctx, filename=None):
- contractor = _binary('contractor')
- _run(ctx, [contractor, 'build', filename])
+ pass
+ argv = _contractor() + ['build', filename]
+ _run(ctx, argv)
# Parse stdout from latest subprocess as JSON into a dict. Read the
@@ -64,6 +80,4 @@ def stdout_json_matches_yaml_file(ctx, filename=None):
dict1 = json.loads(ctx['stdout'])
with open(filename) as f:
dict2 = yaml.safe_load(f)
- print(dict1)
- print(dict2)
assert_eq(dict1, dict2)