ARIA-199 Add "services outputs" CLI command
* Also add an output to hello world example
diff --git a/aria/cli/commands/services.py b/aria/cli/commands/services.py
index 476387c..ae5895a 100644
--- a/aria/cli/commands/services.py
+++ b/aria/cli/commands/services.py
@@ -192,17 +192,16 @@
"""
logger.info('Showing outputs for service {0}...'.format(service_name))
service = model_storage.service.get_by_name(service_name)
- #TODO fix this section..
- outputs_def = service.outputs
- response = model_storage.service.outputs.get(service_name)
- outputs_ = StringIO()
- for output_name, output in response.outputs.iteritems():
- outputs_.write(' - "{0}":{1}'.format(output_name, os.linesep))
- description = outputs_def[output_name].get('description', '')
- outputs_.write(' Description: {0}{1}'.format(description,
- os.linesep))
- outputs_.write(' Value: {0}{1}'.format(output, os.linesep))
- logger.info(outputs_.getvalue())
+
+ if service.outputs:
+ outputs_string = StringIO()
+ for output_name, output in service.outputs.iteritems():
+ outputs_string.write(' - "{0}":{1}'.format(output_name, os.linesep))
+ outputs_string.write(' Description: {0}{1}'.format(output.description, os.linesep))
+ outputs_string.write(' Value: {0}{1}'.format(output.value, os.linesep))
+ logger.info(outputs_string.getvalue())
+ else:
+ logger.info('\tNo outputs')
@services.command(name='inputs',
@@ -218,10 +217,12 @@
"""
logger.info('Showing inputs for service {0}...'.format(service_name))
service = model_storage.service.get_by_name(service_name)
+
if service.inputs:
inputs_string = StringIO()
for input_name, input_ in service.inputs.iteritems():
inputs_string.write(' - "{0}":{1}'.format(input_name, os.linesep))
+ inputs_string.write(' Description: {0}{1}'.format(input_.description, os.linesep))
inputs_string.write(' Value: {0}{1}'.format(input_.value, os.linesep))
logger.info(inputs_string.getvalue())
else:
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index 4102090..f30b86f 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -268,7 +268,7 @@
# See also __all__ at the top of this file
-models_to_register = [
+models_to_register = (
# Service template models
ServiceTemplate,
NodeTemplate,
@@ -317,4 +317,4 @@
Task,
Log,
Argument
-]
+)
diff --git a/examples/hello-world/helloworld.yaml b/examples/hello-world/helloworld.yaml
index be78401..d3369b7 100644
--- a/examples/hello-world/helloworld.yaml
+++ b/examples/hello-world/helloworld.yaml
@@ -1,13 +1,14 @@
tosca_definitions_version: tosca_simple_yaml_1_0
node_types:
- web_server:
+
+ WebServer:
derived_from: tosca.nodes.Root
capabilities:
host:
type: tosca.capabilities.Container
- web_app:
+ WebApp:
derived_from: tosca.nodes.WebApplication
properties:
port:
@@ -17,10 +18,10 @@
node_templates:
web_server:
- type: web_server
+ type: WebServer
web_app:
- type: web_app
+ type: WebApp
properties:
port: 9090
requirements:
@@ -29,4 +30,9 @@
Standard:
configure: scripts/configure.sh
start: scripts/start.sh
- stop: scripts/stop.sh
\ No newline at end of file
+ stop: scripts/stop.sh
+
+ outputs:
+ port:
+ type: integer
+ value: { get_property: [ web_app, port ] }
diff --git a/tests/cli/test_services.py b/tests/cli/test_services.py
index e5717cc..7dc84bc 100644
--- a/tests/cli/test_services.py
+++ b/tests/cli/test_services.py
@@ -174,7 +174,30 @@
class TestServicesOutputs(TestCliBase):
- pass
+
+ def test_header_string(self, monkeypatch, mock_storage):
+ monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+ self.invoke('services outputs test_s')
+ assert 'Showing outputs for service test_s...' in self.logger_output_string
+
+ def test_outputs_no_outputs(self, monkeypatch, mock_storage):
+ monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+ self.invoke('services outputs service_with_no_outputs')
+
+ assert 'No outputs' in self.logger_output_string
+ assert 'output1' not in self.logger_output_string
+ assert 'value1' not in self.logger_output_string
+
+ def test_outputs_one_output(self, monkeypatch, mock_storage):
+ monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
+ s = mock_models.create_service_with_dependencies(include_output=True)
+ monkeypatch.setattr(mock_storage.service, 'get_by_name', mock.MagicMock(return_value=s))
+
+ self.invoke('services outputs test_s')
+
+ assert 'output1' in self.logger_output_string
+ assert 'value1' in self.logger_output_string
+ assert 'No outputs' not in self.logger_output_string
class TestServicesInputs(TestCliBase):
@@ -193,7 +216,6 @@
assert 'value1' not in self.logger_output_string
def test_inputs_one_input(self, monkeypatch, mock_storage):
-
monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
s = mock_models.create_service_with_dependencies(include_input=True)
monkeypatch.setattr(mock_storage.service, 'get_by_name', mock.MagicMock(return_value=s))
diff --git a/tests/end2end/test_hello_world.py b/tests/end2end/test_hello_world.py
index 71792dd..b55b9a8 100644
--- a/tests/end2end/test_hello_world.py
+++ b/tests/end2end/test_hello_world.py
@@ -56,5 +56,6 @@
assert service.name == service_name
assert len(service.executions) == 1
assert len(service.nodes) == 2
+ assert service.outputs['port'].value == 9090
assert all(node.state == node.STARTED for node in service.nodes.values())
assert len(service.executions[0].logs) > 0
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 56a6e3e..7f6bbea 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -86,6 +86,7 @@
def create_service_with_dependencies(include_execution=False,
include_input=False,
+ include_output=False,
include_node=False):
service_template = create_service_template()
service = create_service(service_template=service_template)
@@ -96,6 +97,9 @@
if include_input:
input = create_input(name='input1', value='value1')
service.inputs = {'input1': input}
+ if include_output:
+ output = create_output(name='output1', value='value1')
+ service.outputs = {'output1': output}
if include_node:
node_template = create_node_template(service_template=service_template)
node = create_node(node_template, service, state=models.Node.STARTED)
@@ -290,6 +294,10 @@
return _create_parameter(name, value, model_cls=models.Input)
+def create_output(name, value):
+ return _create_parameter(name, value, model_cls=models.Output)
+
+
def _dictify(item):
return dict(((item.name, item),))
@@ -300,8 +308,8 @@
op_templates = dict(
(op_name, models.OperationTemplate(
name=op_name, implementation='{0}.{1}'.format(__file__, mock_operation.__name__)))
- for op_name in [NORMATIVE_CREATE, NORMATIVE_CONFIGURE, NORMATIVE_START,
- NORMATIVE_STOP, NORMATIVE_DELETE]
+ for op_name in (NORMATIVE_CREATE, NORMATIVE_CONFIGURE, NORMATIVE_START,
+ NORMATIVE_STOP, NORMATIVE_DELETE)
)
return models.InterfaceTemplate(name=NORMATIVE_STANDARD_INTERFACE,
operation_templates=op_templates,
@@ -314,8 +322,8 @@
ops = dict(
(op_name, models.Operation(
name=op_name, implementation='{0}.{1}'.format(__file__, mock_operation.__name__)))
- for op_name in [NORMATIVE_CREATE, NORMATIVE_CONFIGURE, NORMATIVE_START,
- NORMATIVE_STOP, NORMATIVE_DELETE]
+ for op_name in (NORMATIVE_CREATE, NORMATIVE_CONFIGURE, NORMATIVE_START,
+ NORMATIVE_STOP, NORMATIVE_DELETE)
)
return {
NORMATIVE_STANDARD_INTERFACE:
@@ -329,7 +337,7 @@
operations = dict(
(op_name, models.Operation(
name=op_name, implementation='{0}.{1}'.format(__file__, mock_operation.__name__)))
- for op_name in [NORMATIVE_PRE_CONFIGURE_SOURCE,
+ for op_name in (NORMATIVE_PRE_CONFIGURE_SOURCE,
NORMATIVE_POST_CONFIGURE_SOURCE,
NORMATIVE_ADD_SOURCE,
NORMATIVE_REMOVE_SOURCE,
@@ -337,8 +345,7 @@
NORMATIVE_PRE_CONFIGURE_TARGET,
NORMATIVE_POST_CONFIGURE_TARGET,
NORMATIVE_ADD_TARGET,
- NORMATIVE_REMOVE_TARGET
- ]
+ NORMATIVE_REMOVE_TARGET)
)
interface = {
NORMATIVE_CONFIGURE_INTERFACE: models.Interface(
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
index 4d53f9b..a34301c 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
@@ -144,6 +144,10 @@
type: nodejs.Server
requirements:
- host: application_host
+ capabilities:
+ data_endpoint:
+ properties:
+ url_path: /app
node_filter: # cannot be validated
properties:
#- flavor_name: { valid_values: [ {concat:[m1,.,small]} ] } # won't work because not validated :/
@@ -302,6 +306,14 @@
capabilities:
app_endpoint: [ loadbalancer, client ]
+ outputs:
+
+ endpoint:
+ description: >-
+ The application endpoint.
+ type: string
+ value: { get_property: [ nodejs, data_endpoint, url_path ] }
+
policy_types:
MaintenanceWorkflow: