Commit dd7d46ee authored by Daniele Venzano's avatar Daniele Venzano

Merge branch 'master-github'

parents d3f0a180 3d49bb77
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"service-options": {
"type": "object",
"properties": {
"instances": {
"type": "object",
"properties": {
"essential_min": {
"type": "integer"
},
"essential_max": {
"type": "integer"
},
"elastic_min": {
"type": "integer"
},
"elastic_max": {
"type": "integer"
}
},
"additionalProperties": false,
"required": [
"essential_min",
"essential_max",
"elastic_min",
"elastic_max"
]
},
"resources": {
"type": "object",
"properties": {
"memory": {
"type": "object",
"properties": {
"min": {
"type": "integer"
},
"max": {
"type": "integer"
}
},
"additionalProperties": false,
"required": [
"min",
"max"
]
},
"cores": {
"type": "object",
"properties": {
"min": {
"type": "integer"
},
"max": {
"type": "integer"
}
},
"additionalProperties": false,
"required": [
"min",
"max"
]
}
},
"additionalProperties": false,
"required": [
"memory",
"cores"
]
},
"parameters": {
"type": "array",
"items": {
"$ref": "#/definitions/parameter"
},
"uniqueItems": true
}
},
"additionalProperties": false,
"required": ["instances", "resources", "parameters"]
},
"parameter": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [
"environment"
]
},
"type": {
"type": "string",
"enum": [
"int",
"string"
]
},
"name": {
"type": "string"
},
"readable_name": {
"type": "string"
},
"description": {
"type": "string"
},
"default": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"min": { "type": "integer" },
"max": {
"type": "integer"
}
},
"required": ["kind", "type", "name", "readable_name", "description", "default"]
}
},
"type": "object",
"properties": {
"name": {"type": "string"},
"version": {"type": "string"},
"package_version": {
"type": "integer",
"enum": [1]
},
"maintainer": {"type": "string"},
"license": {"type": "string"},
"options": {
"type": "object",
"patternProperties": {
"[a-z\\-]": { "$ref": "#/definitions/service-options" }
},
"minItems": 1
}
},
"additionalProperties": false,
"required": ["name", "version", "package_version", "maintainer", "license"]
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"service": {
"type": "object",
"properties": {
"group": {
"type": "string"
},
"image": {
"type": "string"
},
"ports": {
},
"environment": {
},
"volumes": {
},
"startup_order": {
"type": "integer"
}
},
"additionalProperties": false,
"required": ["group", "image", "ports", "environment", "volumes", "startup_order"]
}
},
"type": "object",
}
#!/usr/bin/python3
# Copyright (c) 2017, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Manage ZApp packages.
"""
import logging
from zoe_lib.zapps.zapp_storage import ZAppStorage
from zoe_lib.zapps.zapp_package import ZAppPackage
import zoe_lib.config as config
def list_zapps():
"""List all ZApps available in the local store."""
zapp_store = ZAppStorage()
zapps = zapp_store.list()
for zapp in zapps: # type: ZAppPackage
print('{} {} {} (by {})'.format(zapp.id, zapp.name, zapp.version, zapp.maintainer))
def load_zapp(id):
"""Loads a specific ZApp given its ID."""
zapp_store = ZAppStorage()
zapp = zapp_store.load(id)
if zapp is None:
print('Cannot find the {} ZApp'.format(id))
return
tmp = zapp.generate_app_description()
import pprint; pprint.pprint(tmp)
def main():
"""Main entrypoint."""
config.load_configuration()
args = config.get_conf()
if args.debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
logging.getLogger("requests").setLevel(logging.WARNING)
load_zapp('sleeper:1.0')
if __name__ == '__main__':
main()
# Copyright (c) 2017, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The ZApp packaging definition."""
import json
import os
from jsonschema import validate as json_schema_validate, ValidationError
from zoe_api.exceptions import ZoeException
from zoe_lib.config import get_conf
PACKAGE_VERSION = 1
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
METADATA_SCHEMA_PATH = os.path.realpath(os.path.join(__location__, "..", "..", "schemas", "zapp_metadata_schema.json"))
class ZAppPackage:
"""A ZApp package."""
METADATA_FILE = 'metadata.json'
TEMPLATE_FILE = 'services.json'
DOCS_FILE = 'README.md'
def __init__(self, load_path):
self.load_path = load_path
self.id = ''
# Metadata
self.name = ''
self.version = ''
self.package_version = 0
self.maintainer = ''
self.license = ''
self.sanity_check()
self._load_metadata()
def sanity_check(self):
"""Check that a ZApp package is in the right format."""
if not os.access(os.path.join(self.load_path, self.METADATA_FILE), os.R_OK):
raise ZoeException('No metadata file in ZApp package at {}'.format(self.load_path))
if not os.access(os.path.join(self.load_path, self.DOCS_FILE), os.R_OK):
raise ZoeException('No readme file in ZApp package at {}'.format(self.load_path))
if not os.access(os.path.join(self.load_path, self.TEMPLATE_FILE), os.R_OK):
raise ZoeException('No template file in ZApp package at {}'.format(self.load_path))
def _load_metadata(self):
fpath = os.path.join(self.load_path, self.METADATA_FILE)
schema = json.load(open(METADATA_SCHEMA_PATH, 'r'))
metadata = json.load(open(fpath, 'r'))
json_schema_validate(metadata, schema)
# Code for handling previous package versions goes here
self.package_version = metadata['package_version']
self.name = metadata['name']
self.version = metadata['version']
self.maintainer = metadata['maintainer']
self.license = metadata['license']
self.id = self.name + ':' + self.version
def _load_template(self):
fpath = os.path.join(self.load_path, self.TEMPLATE_FILE)
return json.load(open(fpath, 'r'))
def generate_app_description(self):
"""Generate a Zoe application description by instantiating the template."""
template = self._load_template()
app_descr = {
'name': self.name,
'services': [],
'version': 3,
}
for service in template['services']:
service['image'] = get_conf().registry + '/' + get_conf().registry_repository + '/' + service['image'] + ":" + self.version
app_descr['services'].append(service)
return app_descr
# Copyright (c) 2017, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The ZApp storage manager. It adds, lists, loads and deletes ZApps from the internal store."""
import os
from zoe_lib.config import get_conf
from zoe_lib.exceptions import ZoeLibException
from zoe_lib.zapps.zapp_package import ZAppPackage
ZAPP_STORAGE_PATH = 'zapps'
class ZAppStorage:
"""The ZApp storage manager. It adds, lists, loads and deletes ZApps from the internal store."""
def __init__(self):
self.path = os.path.join(get_conf().zapp_storage, ZAPP_STORAGE_PATH)
try:
os.makedirs(self.path, exist_ok=True)
except OSError:
raise ZoeLibException(message='Cannot create directory {}'.format(self.path))
def list(self):
"""Loads all ZApps from the storage directory and returns a list of ZAppPackage objects."""
all_zapps = []
for zapp_dir in os.listdir(self.path):
zapp = ZAppPackage(os.path.join(self.path, zapp_dir))
all_zapps.append(zapp)
return all_zapps
def load(self, id):
"""Loads a specific ZApp given its ID."""
zapps = self.list()
for zapp in zapps:
if zapp.id == id:
return zapp
return None
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment