Add docs for App Catalog:

* muranoPL specification
* dynamic UI specification
* How to upload application package

Change-Id: Ic62f356c237b76747c20aa9c3757a68443b88ca6
This commit is contained in:
Ekaterina Fedorova 2014-04-30 19:25:19 +04:00
parent aa6aa6f511
commit af9026475e
6 changed files with 860 additions and 0 deletions

View File

@ -0,0 +1,176 @@
..
Copyright 2014 2014 Mirantis, Inc.
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.
====================================
Composing application package manual
====================================
Murano is Application catalog that supports types of applications. This document intends to make composing application packages easily.
Step 1. Prepare Execution Plans
================================
An *Execution Plan* is a set of metadata that describes the installation process of an application in a virtual machine.
It's a minimal unit of execution that can be triggered in Murano Workflows and should be understandable by Murano agent. From *Execution plans* any script can be triggered.
It could be any type of scripts which will execute commands and install application components as the result. Each script may consist of one or more files.
Scripts may be reused across several Execution Plans. One of the scripts should be an entry point and should be specified in a resource template file in *Scripts*.
Besides the *Scripts* section the following sections must be presented in a resource template file:
* **FormatVersion** - version of *Execution Plan* syntax format
* **Version** - version of *Execution Plan*
* **Name** - human-readable name of the Execution Plan
* **Parameters** - parameters received from MuranoPL
* **Body** - Python statement, should start with | symbol
* **Scripts** - dictionary that maps script names to script definitions.
Scripts are the building blocks of Execution Plans and they may be executed as a whole (like a single piece of code), expose some functions that can be independently called in scripts. This depends on Deployment Platform and Executor capabilities. One script can be defined with the following properties
* **Type** Deployment Platform name that script is targeted to.
* **Version** optional minimum version of deployment platform/executor required by the script.
* **EntryPoint** relative path to the file that contains a script entry point
* **Files** This is an optional array of additional files required for the script. Use *<>* to specify a relative path to the file. The root directory is *Resource/scripts*.
* **Options** an optional argument of type contains additional options
Example *DeployTelnet.template*
.. code-block:: yaml
FormatVersion: 2.0.0
Version: 1.0.0
Name: Deploy Telnet
Parameters:
appName: $appName
Body: |
return deploy(args.appName).stdout
Scripts:
deploy:
Type: Application
Version: 1.0.0
EntryPoint: deployTelnet.sh
Files:
- installer.sh
- common.sh
Options:
captureStdout: true
captureStderr: false
Step 2. Prepare MuranoPL class definitions
===========================================
MuranoPL classes control application deployment workflow execution. Full information about MuranoPL classes see here: :ref:`MuranoPL Spec`
Example *telnet.yaml*
.. code-block:: yaml
Namespaces:
=: io.murano.apps.linux
std: io.murano
res: io.murano.resources
Name: Telnet
Extends: std:Application
Properties:
name:
Contract: $.string().notNull()
instance:
Contract: $.class(res:Instance).notNull()
Workflow:
deploy:
Body:
- $this.find(std:Environment).reporter.report($this, 'Creating VM for Telnet instace.')
- $.instance.deploy()
- $this.find(std:Environment).reporter.report($this, 'Instance is created. Setup Telnet service.')
- $resources: new('io.murano.system.Resources')
# Deploy Telnet
- $template: $resources.yaml('DeployTelnet.template')
- $.instance.agent.call($template, $resources)
- $this.find(std:Environment).reporter.report($this, 'Telnet service setup is done.')
Note, that
* *io.murano.system.Resources* is a system class, defined in MuranoPL.
* *io.murano.resources.Instance* is a class, defined in the core Murano library, which is available here. This library contains Murano agent templates and init scripts.
* $this.find(std:Environment).reporter.report($this, 'Creating VM for Telnet instace.') - this is the way of sending reports to Murano dashboard during deployment
Step 3. Prepare dynamic UI form definition
===========================================
Create a form definition in a yaml format. Before configuring a form, compose a list of parameters that will be required to set by a user.
Some form fields that are responsible for choosing a flavor, image and availability zone are better to use in every application creation wizard.
Syntax of Dynamic UI can be found see here: :ref:`Dynamic UI Spec`
Full example with Telnet application form definition is available here :ref:`telnet-yaml`
Step 4. Prepare application logo
=================================
Find or create a simple image (in a .png format) associated with your application. Is should be small and have a square shape. You can specify any name of your image. In our example, let's name it *telnet.png*.
Step 5. Prepare manifest file
==============================
General application metadata should be described in the application manifest file. It should be in a yaml format and should have the following sections
* **Format** - version of a manifest syntax format
* **Type** - package type. Valid choices are *Library* and *Application*
* **Name** - human-readable application name
* **Description** - a brief description of an application
* **Author** - person or company name which created an application package
* **Classes** - MuranoPL class list, on which application deployment is based
* **Tags** - list of words, associated with this application. Will be helpful during the search. *Optional* parameter
Example *manifest.yaml*
.. code-block:: yaml
Format: 1.0
Type: Application
FullName: io.murano.apps.linux.Telnet
Name: Telnet
Description: |
Telnet is the traditional protocol for making remote console connections over TCP.
Author: 'Mirantis, Inc'
Tags: [Linux, connection]
Classes:
io.murano.apps.linux.Telnet: telnet.yaml
UI: telnet.yaml
Logo: telnet.png
Step 6. Compose a zip archive
==============================
An application archive should have the following structure
* *Classes* folder
MuranoPL class definitions should be put inside this folder
* *Resources* folder
This folder should contain Execution scripts
* *Scripts* folder
All script files, needed for an application deployment should be placed here
* *UI* folder
Place dynamic ui yaml definitions here or skip to use the default name *ui.yaml*
* *logo.png*
Image file should be placed in the root folder. It can have any name, just specify it in the manifest file or skip to use default *logo.png* name
* *manifest.yaml*
Application manifest file. It's an application entry point. The file name is fixed.
Congratulations! Your application is ready to be uploaded to an Application Catalog.

View File

@ -0,0 +1,145 @@
..
Copyright 2014 Mirantis, Inc.
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.
.. _Dynamic UI Spec:
===================================
Dynamic UI Definition specification
===================================
The main purpose of Dynamic UI is to generate application creation forms "on-the-fly".
Murano dashboard doesn't know anything about what applications can be deployed and which web form are needed to create application instance.
So all application definitions should contain a yaml file which tells dashboard how to create an application and what validations are to be applied.
This document will help you to compose a valid UI definition for your application.
Structure
=========
UI definition should be a valid yaml file and should contain the following sections (for version 2):
* **Version** - points out to which syntax version is used, optional
* **Templates** - optional, auxiliary section, used together with an Application section, optional
* **Application** - object model description which will be used for application deployment, required
* **Forms** - web form definitions, required
Version
=======
Version of supported dynamic UI syntax. The latest version is 2.
This is optional section, default version is set to 1.
Version mapping:
Murano 0.4 - version 1
Murano 0.5 - version 2
Application and Templates
=========================
In the Application *application object model* section is described. This model will be translated into json and according to that json application will be deployed.
Application section should contain all necessary keys that are required by murano-engine to deploy an application. Note that under ''?'' section goes system part of the model.
You can pick parameters you got from the user (they should be described in the Forms section) and pick the right place where they should be set.
To do this `YAQL <https://github.com/tsufiev/yaql/blob/master/README.md>`_ is used. All lines are going to be checked for a yaql expressions. Thus, *generateHostname* will be recognized as yaql function and will generate machine hostname .
*Example:*
.. code-block:: yaml
primaryController:
?:
type: io.murano.windows.activeDirectory.PrimaryController
host:
?:
type: io.murano.windows.Host
adminPassword: $.serviceConfiguration.adminPassword
name: generateHostname($.serviceConfiguration.unitNamingPattern, 1)
flavor: $.instanceConfiguration.flavor
image: $.instanceConfiguration.osImage
secondaryController:
?:
type: io.murano.windows.activeDirectory.SecondaryController
host:
?:
type: io.murano.windows.Host
adminPassword: $.serviceConfiguration.adminPassword
name: generateHostname($.serviceConfiguration.unitNamingPattern, $index + 1)
flavor: $.instanceConfiguration.flavor
image: $.instanceConfiguration.osImage
Forms
=====
This section describes Django forms. Set name for your form and provide fields and validators.
Each field should contain:
* **name** - system field name, could be any
* **label** - name, that will be displayed in the form
* **description** - description, that will be displayed in the form description area. Use yaml line folding character >- to keep the correct formatting during data transferring.
* **type** - system field type
* string - Django string field
* boolean - Django boolean field
* text - Django boolean field
* integer - Django integer field
* password - Specific field with validation for strong password
* clusterip - Specific field, used for cluster IP
* domain - Specific field, used for Active Directory domain
* databaselist - Specific field, a list of databases (comma-separated list of database names, where each name has the following syntax first symbol should be latin letter or underscore; subsequent symbols can be Latin letter, numeric, underscore, at the sign, number sign or dollar sign)
* table - Specific field, used for defining table in a form
* flavor - Specific field, used for defining flavor in a form
* keypair - Specific field, used for defining KeyPair in a form
* image- Specific field, used for defining image in a form
* azone - Specific field, used for defining availability zone in a form
*Example*
.. code-block:: yaml
Forms:
- serviceConfiguration:
fields:
- name: name
type: string
label: Service Name
description: >-
To identify your service in logs please specify a service name
- name: dcInstances
type: integer
hidden: true
initial: 1
required: false
maxLength: 15
helpText: Optional field for a machine hostname template
- instanceConfiguration:
fields:
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
imageType: linux
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false
Full example with Telnet application form definitions is available here :ref:`telnet-yaml`

View File

@ -0,0 +1,25 @@
..
Copyright 2014 Mirantis, Inc.
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.
============
App Catalog
============
.. toctree::
:maxdepth: 2
murano_pl
dynamic_ui
app_pkg

View File

@ -0,0 +1,389 @@
..
Copyright 2014 2014 Mirantis, Inc.
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.
.. _MuranoPL Spec:
======================
MuranoPL specification
======================
YAML
====
YAML is human-readable data serialization format that is a superset of JSON. Unlike JSON YAML was designed to be read and written by humans and relies on visual indentation to denote nesting of data structures. This is similar to how Python uses indentation for block structures instead of curly brackets in most C-like languages. Also YAML can contain more data types comparing to JSON. See http://yaml.org/ for detailed description of YAML.
MuranoPL was designed to be representable in YAML so that MuranoPL code could remain readable and structured. Thus usually MuranoPL files are YAML encoded documents. But MuranoPL engine itself doesn't deal directly with YAML documents and it is up to hosting application to locate and deserialize definitions of particular classes. This gives hosting application ability to control where those definitions can be found (file system, database, remote repository etc) and possibly use some other serialization formats instead of YAML.
MuranoPL engine relies on host deserialization code to automatically detect YAQL expressions in source definition and to provide them as instances of YaqlExpression class rather than plain strings. Usually YAQL expressions can be distinguished by presence of $ (dollar sign) and operators but in YAML developer can always explicitly state the type by using YAML tags. So
::
Some text - a string,
$.something() - YAQL
"$.something()" - string (because of quote marks)
!!str $ - a string (because of YAML tag)
!yaql "text" - YAQL (because of YAML tag)
YAQL
====
YAQL (Yet Another Query Language) is a query language that was also designed as part of Murano project. MuranoPL makes an extensive use of YAQL. YAQL description can be found here: https://github.com/ativelkov/yaql
In simple words YAQL is a language for expression evaluation. ``2 + 2, foo() > bar(), true != false`` are all valid YAQL expressions. The interesting thing in YAQL is that it has no built in list of functions. Everything YAQL can access is customizable. YAQL cannot call any function that was not explicitly registered to be accessible by YAQL. The same is true for operators. So the result of expression 2 * foo(3, 4) is completely depended on explicitly provided implementations of "foo" and "operator_*".
YAQL uses dollar sign ($) to access external variables (that are also explicitly provided by host application) and function arguments. ``$variable`` is a syntax to get the value of variable "$variable",
$1, $2 etc are the names for function arguments. "$" is a name for current object - data on which the expression is evaluated or a name of a single argument. Thus $ in the beginning of expression and $ in middle of it can refer to different things.
YAQL has a lot of functions out of the box that can be registered in YAQL context. For example
``$.where($.myObj.myScalar > 5 and $.myObj.myArray.len() > 0 and $.myObj.myArray.any($ = 4)).select($.myObj.myArray[0])`` can be executed on ``$ = array`` of objects and has a result of another array that is a filtration and projection of a source data. This is very similar to how SQL works but uses more Python-like syntax.
Note that there is no assignment operator in YAQL and '=' means comparision operator that is what '==' means in Python.
Because YAQL has no access to underlying operating system resources and 100% controllable by the host it is secure to execute YAQL expressions without establishing a trust to executed code. Also because of the functions are not predefined different functions may be accessible in different contexts. So the YAQL expressions that are used to specify property contracts are not necessarily valid in workflow definitions.
Common class structure
======================
Here is a common template for class declarations. In sections below I'm going to explain what each section means. Note that it is in YAML format.
.. code-block:: yaml
Name: class name
Namespaces: namespaces specification
Extends: [list of parent classes]
Properties: properties declaration
Workflow:
methodName:
Arguments:
- list
- of
- arguments
Body:
- list
- of
- instructions
Thus MuranoPL class is a YAML dictionary with predefined key names. All keys except for Name are optional and can be omitted (but must be valid if present)
Class name
----------
Class names are alphanumeric names of the classes. By tradition all class names begin with upper-case letter and written in PascalCasing.
In Murano all class names are globally unique. This achieved by means of namespaces. Class name may have explicit namespace specification (like ns:MyName) or implicit (just MyName which would be equal to =:MyName if = was a valid in name specification)
Namespaces
----------
Namespaces declaration specifies prefixes that can be used in class body to make long class names shorter.
.. code-block:: yaml
Namespaces:
=: io.murano.services.windows
srv: io.murano.services
std: io.murano
In example above class name srv:Something would be automatically translated to "io.murano.services.Something".
"=" means "current namespace" so that "MyClass" would mean "io.murano.services.windows.MyClass" in example above.
If class name contains period sign (.) in its name then it is assumed to be already fully namespace-qualified and is not expanded. Thus ns.Myclass would remain as is.
To make class names globally unique it is recommended to have developer's domain name as part of namespace (as in example, similar to Java)
Extends
-------
MuranoPL supports multiple inheritance. If present, Extends section lists base classes that are extended. If the list consists of single entry then it may be written as a scalar string instead of array. If no parents specified (or a key is omitted) then "io.murano.Object" is assumed making it the root class for all class hierarchies.
Properties
----------
Properties are class attributes that together with methods form public class interface. Usually (but not always) properties are the values and references to other objects that are required to be entered in environment designer prior to workflow invocation.
Properties have the following declaration format:
.. code-block:: yaml
propertyName:
Contract: property contract
Usage: property usage
Default: property default
Contract
^^^^^^^^
Contracts are YAQL expressions that say what type of value is expected for the property as well as additional constraints imposed on the property.
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| Operation | Definition |
+===========================================================+=================================================================================================+
| $.int() | integer value (may be null). String values that consist of digits would be converted to integer|
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| $.int().notNull() | mandatory integer |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | $.string() | the same for strings. If the supplied value is not a string it will be converted to string |
| | $.string().notNull() | |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | $.bool() | bools are true and false. 0 is converted to false, other integers to true |
| | $.bool().notNull() | |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | $.class(ns:ClassName) | value must be a reference to an instance of specified class name |
| | $.class(ns:ClassName).notNull() | |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| $.class(ns:ClassName, ns:DefaultClassName) | create instance of ns:DefaultClassName class if no instance provided |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| $.class(ns:Name).check($.p = 12) | value must be of type ns:Name and have a property 'p' equal to 12 |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | [$.int()] | array of integers. Similar for other types |
| | [$.int().notNull()] | |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| [$.int().check($ > 0)] | array of positive integers (thus not null) |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| [$.int(), $.string()] | array that has at least two elements, first is int and others are strings |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | [$.int(), 2] | | array of ints with at least 2 items |
| | [$.int(), 2, 5] | | ... and maximum of 5 items |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| { A: $.int(), B: [$.string()] } | dictionary with 'A' key of type int and 'B' - array of strings |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | $ | any scalar or data structure as is |
| | [] | any array |
| | {} | any dictionary |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| { $.string().notNull(): $.int().notNull() } | dictionary string -> int |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
| | A: StringMap | dictionary with 'A' key that must be equal to 'StringMap' and other keys be any scalar or data |
| | $.string().notNull(): $ | structure |
+-----------------------------------------------------------+-------------------------------------------------------------------------------------------------+
Usage
^^^^^
Usage states purpose of the property. This implies who and how can access it. The following usages are available:
=========== ==================================================================================================================================================
Property Explanation
=========== ==================================================================================================================================================
``In`` Input property. Values of such properties are obtained from user and cannot be modified in MuranoPL workflows. This is default value for Usage key
``Out`` The value is obtained from executing MuranoPL workflow and cannot be modified by the user
``InOut`` Value can be edited by both user and workflow
``Const`` The same as In but once workflow is executed the property cannot be changed neither by user not the workflow
``Runtime`` Property is visible only from within workflows. It neither read from input neither serialized to workflow output
=========== ==================================================================================================================================================
Usage attribute is optional and can be omitted (which implies In).
If the workflow tries to write to a property that is not declared with one of the types above it is considered to be private and accessible only to that class (and not serialized to output and thus would be lost upon next deployment). Attempt to read property that wasn't initialized causes exception to be thrown.
Default
^^^^^^^
Default is a value that would be used if the property value wasn't mentioned in input object model (but not when it is provided as null). Default (if specified) must conform to declared property contract. If Default is not specified then null is the default.
For properties that are references to other classes Default can modify default values for referenced value. For example
::
p:
Contract: $.class(MyClass)
Default: {a: 12}
would override default for 'a' property of MyClass for instance of MyClass that is created for this property.
Workflow
--------
Workflows are the methods that together describe how the entities that are represented by MuranoPL classes are deployed.
In typical scenario root object in input data model is of type io.murano.Environment and has a "deploy" method. Invoking this method causes a series of infrastructure activities (typically by modifying Heat stack) and VM agents commands that cause execution of deployment scripts. Workflow role is to map data from input object model (or result of previously executed actions) to parameters of those activities and to initiate those activities in correct order.
Methods have input parameters and can return value to the caller.
Methods defined in Workflow section of the class using the following template:
::
methodName:
Arguments:
- list
- of
- arguments
Body:
- list
- of
- instructions
Arguments are optional and (if specified) declared using the same syntax as class properties except for Usage attribute that is meaningless for method parameters. E.g. arguments also have a contract and optional default.
Method body is an array of instructions that got executed sequentially. There are 3 types of instructions that can be found in workflow body: expressions, assignment and block constructs.
Expressions
^^^^^^^^^^^
Expressions are YAQL expressions that are executed for their side effect. All accessible object methods can be called in expression using $obj.methodName(arguments) syntax.
+-------------------------------------------+----------------------------------------------------------------+
| Expression | Explanation |
+===========================================+================================================================+
| | ``$.methodName()`` | invoke method 'methodName' on this (self) object |
| | ``$this.methodName()`` | |
+-------------------------------------------+----------------------------------------------------------------+
| | ``$.property.methodName()`` | invocation of method on object that is in 'property' property |
| | ``$this.property.methodName()`` | |
+-------------------------------------------+----------------------------------------------------------------+
| ``$.method(1, 2, 3)`` | methods can have arguments |
+-------------------------------------------+----------------------------------------------------------------+
| ``$.method(1, 2, thirdParameter => 3)`` | named parameters also supported |
+-------------------------------------------+----------------------------------------------------------------+
| ``list($.foo().bar($this.property), $p)`` | complex expressions can be constructed |
+-------------------------------------------+----------------------------------------------------------------+
Assignment
^^^^^^^^^^
Assignments are single-key dictionaries with YAQL expression as key and arbitrary structure as a value. Such construct evaluated as assignment.
+--------------------------------+-------------------------------------------------------------------------------------------------+
| Assignment | Explanation |
+================================+=================================================================================================+
| ``$x: value`` | assigns value to local variable $x |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| ``$.x: value`` | assign value to objects property |
| ``$this.x: value`` | |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| ``$.x: $.y`` | copy value of property 'y' to property 'x' |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| ``$x: [$a, $b]`` | sets $x to array of 2 values $a and $b |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| | ``$x:`` | structures of any level of complexity can be evaluated |
| | ``SomeKey:`` | |
| | ``NestedKey: $variable`` | |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| ``$.x[0]: value``` | assign value to a first array entry of property x |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| ``$.x.append(): value`` | append value to array in property x |
+--------------------------------+------------------------------+------------------------------------------------------------------+
| ``$.x.insert(1): value`` | insert value into position 1 |
+--------------------------------+-------------------------------------------------------------------------------------------------+
| | ``$.x.key.subKey: value`` | deep dictionary modification |
| | ``$.x[key][subKey]: value`` | |
+--------------------------------+-------------------------------------------------------------------------------------------------+
Block constructs
^^^^^^^^^^^^^^^^
Block constructs control program flow. Block constructs are dictionaries that have strings as all its keys.
The following block constructs are available:
+---------------------------------+----------------------------------------------------------------------------------------+
| Assignment | Explanation |
+=================================+========================================================================================+
| ``Return: value`` | return value from a method |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``If: predicate()`` | predicate() is YAQL expressions that must be evaluated to true or false. |
| | ``Then:`` | |
| | ``- code`` | else part is optional |
| | ``- block`` | |
| | ``Else:`` | one-line code blocks can be written as a scalars rather than array. |
| | ``- code`` | |
| | ``- block`` | |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``While: predicate()`` | predicate() must be evaluated to true or false |
| | ``Do:`` | |
| | ``- code`` | |
| | ``- block`` | |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``For: variableName`` | collection must be YAQL expression returning iterable collection or |
| | ``In: collection`` | evaluatable array as in assignment instructions (like [1, 2, $x]) |
| | ``Do:`` | |
| | ``- code`` | inside code block loop variable is accessible as $variableName |
| | ``- block`` | |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``Repeat:`` | repeat code block specified number of times |
| | ``Do:`` | |
| | ``- code`` | |
| | ``- block`` | |
+---------------------------------+----------------------------------------------------------------------------------------+
| Break: | breaks from loop |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``Match:`` | matches result of $valueExpression() against set of possible values (cases). |
| | ``case1:`` | the code block of first matched cased is executed. |
| | ``- code`` | |
| | ``- block`` | if not case matched and Default key is present (it is optional) |
| | ``case2:`` | than Default code block get executed. |
| | ``- code`` | case values are constant values (not expressions) |
| | ``- block`` | |
| | ``Value: $valueExpression()`` | |
| | ``Default:`` | |
| | ``- code`` | |
| | ``- block`` | |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``Switch:`` | all code blocks that have their predicate evaluated to true are executed but the order |
| | ``$predicate1() :`` | of predicate evaluation is not fixed |
| | ``- code`` | |
| | ``- block`` | |
| | ``$predicate2() :`` | |
| | ``- code`` | |
| | ``- block`` | |
| | ``Default:`` | default key is optional. |
| | ``- code`` | |
| | ``- block`` | if no predicate evaluated to true than Default code block get executed. |
+---------------------------------+----------------------------------------------------------------------------------------+
| | ``Parallel:`` | executes all instructions in code block in separate green threads in parallel |
| | ``- code`` | |
| | ``- block`` | |
| | ``Limit: 5`` | limit is optional and means the maximum number of concurrent green threads. |
+---------------------------------+----------------------------------------------------------------------------------------+
Object model
------------
Object model is JSON-serialized representation of objects and their properties. Everything user does in environment builder (dashboard) is reflected in object model. Object model is sent to App Catalog engine upon user decides to deploy built environment. On engine side MuranoPL objects are constructed and initialized from received Object model and predefined method is executed on a root object.
Objects serialized to JSON using the following template:
.. code-block:: yaml
{
"?": {
"id": "globally unique object ID (UUID)",
"type": "fully namespace-qualified class name",
"optional designer-related entries can be placed here": {
"key": "value"
}
},
"classProperty1": "propertyValue",
"classProperty2": 123,
"classProperty3": ["value1", "value2"],
"reference1": {
"?": {
"id": "object id",
"type": "object type"
},
"property": "value"
},
"reference2": "referenced object id"
}
Objects can be identified as dictionaries that contain "?" entry. All system fields are hidden in that entry.
There are 2 ways to specify references. The first method ("reference1" in example above) allow inline definition of object. When instance of referenced object is created outer object becomes its parent (owner) that is responsible for the object. The object itself may require that its parent (direct or indirect) be of specified type (like all application require to have Environment somewhere in parent chain).
Second way to reference object is by specifying other object id. That object must be defined somewhere else in object tree. Object references distinguished from strings having the same value by evaluating property contracts. The former case would have $.class(Name) while the later $.string() contract.

View File

@ -0,0 +1,124 @@
..
Copyright 2014 2014 Mirantis, Inc.
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.
.. _telnet-yaml:
=============
*telnet.yaml*
=============
.. code-block:: yaml
Version: 2
Templates:
instance:
?:
type: io.murano.resources.Instance
name: generateHostname($.appConfiguration.unitNamingPattern, 1)
flavor: $.instanceConfiguration.flavor
image: $.instanceConfiguration.osImage
assignFloatingIp: $.appConfiguration.assignFloatingIP
Application:
?:
type: io.murano.apps.linux.Telnet
name: $.appConfiguration.name
instance: $instance
Forms:
- appConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
description: Telnet is a service that allows a Telnet client to connect across a network and access a command session
- name: name
type: string
label: Application Name
description: >-
Enter a desired name for the application. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: dcInstances
type: integer
hidden: true
initial: 1
- name: assignFloatingIP
type: boolean
label: Assign Floating IP
description: >-
Select to true to assign floating IP automatically
initial: false
required: false
widgetMedia:
css: {all: ['muranodashboard/css/checkbox.css']}
- name: unitNamingPattern
type: string
label: Hostname
description: >-
For your convenience instance hostname can be specified.
Enter a name or leave blank for random name generation.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname
# temporaryHack
widgetMedia:
js: ['muranodashboard/js/support_placeholder.js']
css: {all: ['muranodashboard/css/support_placeholder.css']}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: $.appConfiguration.dcInstances < 2 or not $.appConfiguration.unitNamingPattern.bool() or '#' in $.appConfiguration.unitNamingPattern
message: Incrementation symbol "#" is required in the Hostname template
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
description: Specify some instance parameters on which the application would be created
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that application performance
depends on this parameter.
required: false
- name: osImage
type: image
imageType: linux
label: Instance image
description: >-
Select valid image for the application. Image should have Murano agent installed and
registered in Glance.
- name: keyPair
type: keypair
label: Key Pair
description: >-
Select the Key Pair to control access to instances. You can login to
instances using this KeyPair after application deployment
required: false
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where the application would be installed.
required: false

View File

@ -57,6 +57,7 @@ Table of contents
contributing
guidelines
install/index
articles/index
Indices and tables