In this section we show how the concepts of EDMM can be semantically mapped to the selected deployment technologies. The mapping is structured into three subsections according to the categories presented in Sect. 3.
EDMM to GP-technology mapping
We hereby show how the EDMM can be semantically mapped to Puppet, Chef, Ansible, OpenStack Heat, Terraform, SaltStack, Juju, and Cloudify. All of these technologies support the required features and mechanisms as outlined in Sect. 2.3.
Mapping to Puppet
In Puppet, resources are the main building blocks describing certain aspects of the system. For example, in our reference application, the deployment of a component can be described by a resource. The semantic and structure of a resource is defined by its assigned resource type (cf. Definition 2). Puppet provides a set of built-in resource types which can be extended by custom resource types written in Ruby. Resources can be bundled to modules enabling the encapsulation of logical parts into reusable entities (cf. Definition 2), e.g., the stack of the Order App in our reference scenario can be encapsulated using a module. Resources or modules can be used in the resulting deployment model and can be mapped to components encompassing certain semantics. Both, modules and resources utilize properties, e.g., to define a port a web server is listening on. In addition, artifacts can be defined that implement the component, e.g., by defining in a module to use a compressed version of the Tomcat web server. Modules contain a set of classes expressing the logic to converge components into a certain state and can be mapped to operations in EDMM. In Puppet, relations between components can be expressed on different levels and are limited to a predefined set of relation types. By including another module the semantic of a “depends on” relation type can be expressed. On the level of classes, a “depends on” relation can be defined by using a predefined require function.
Mapping to chef
Chef uses cookbooks to structure and encapsulate logical parts of a deployment model. Cookbooks can be mapped to components as well as to component types in our metamodel. Using cookbooks, reusable entities can be defined expressing certain semantics, which map to component types. Further, cookbooks can be imported into other cookbooks, which maps semantically to components in this context. Our reference application (Fig. 1) can be expressed in a single cookbook by importing existing ones from the Chef supermarket, e.g., a cookbook to install a Tomcat web server. In Chef, all kinds of artifact are supported as long as they can be referenced and packaged using the provided mechanisms. The actual operations to be executed to install or configure a component are encapsulated in so called recipes written in Ruby. Cookbooks can have dependencies to other cookbooks by using the depends attribute in the respective meta data file. With include_recipe, operations from dependent cookbooks can be integrated in the sequence of operations required to reach a desired state. Thus, relations of one relation type can be expressed. By using an attribute file that, for example, defines the desired port of a web server, inputs for properties in the recipes can be represented in Chef.
Mapping to Ansible
Ansible and Chef are similar in their concepts. Like in Chef, playbooks are the elements used to create deployment models. For example, the complete reference scenario can be expressed in a single playbook. As playbooks can also encapsulate logical and reusable parts, they can be mapped to components and component types due to their recursive aggregation behavior. There can be a generic “Tomcat” playbook that enables the deployment and configuration of an Tomcat web server. Playbooks can also define variables that are mapped to properties in EDMM. In Ansible, relations, such as a web application is hosted on a web server, are implicitly defined by importing other Playbooks and can only expressed a “depends on” relation type. Ansible uses the concept of “roles”, which contain “tasks” to converge a system to a desired state. Roles are part of playbooks and mapped to operations and, therein, all kinds of artifacts are supported that implement a component.
Mapping to OpenStack Heat
The deployment model for OpenStack Heat is called Heat Orchestration Template (HOT). The logical parts of an application, i.e., its components are modeled as resources. Several resource types are provided by Heat and further plugins for other resources are already available (e.g., Docker or AWS) or can be created. These resource types are reusable entities that specify the properties and operations that can be executed on a resource of this type. They form the component types in Heat. For deployments on a VM (such as for the Admin App in Fig. 1) an infrastructure, a Heat::SoftwareConfig, and a Heat::SoftwareDeployment resource are used. The supported artifacts that implement a component depend on the resource type. With a SoftwareConfig resource (restricted to be used only with other IaaS resources) arbitrary operations can be specified and linked to implementation artifact, e.g., in the form of executable scripts. To express dependencies between components, the dependsOn attribute can be used where one or more other components can be referenced. Further types of relations and, thus, relation types can be expressed using certain properties of a component.
Mapping to Terraform
In Terraform, resources are used to describe elements of a deployment model, e.g., compute instances, virtual networks, or software components. Each resource is assigned to a resource type that determines the kind of element that is managed and specifies properties in the form of so-called attributes. Several resource types are provided by Terraform and custom resource types can be written in Go. Resources and resource types are mapped to components and component types respectively. The supported artifacts that implement a component depend on the resource type. In addition, provisioners can be defined that are executed as part of the creation or destruction of a resource. For example, the remote-exec provisioner can be used to define arbitrary operations that are executed on a resource after its creation, e.g., downloading and installing an Apache Tomcat server on a provisioned EC2 instance. Explicit dependencies between resources can be expressed by the use of the depends_on attribute. Further, modules can be used to create logical, reusable groups of resources. Input Variables on modules are mapped to properties and are used to parameterize and customize modules. For example, each stack of the reference scenario can be expressed by a Terraform module specifying the required resources. Hence, modules are mapped to components and component types in EDMM.
Mapping to SaltStack
SaltStack is a flexible orchestration and configuration management tool, which uses so-called top files to create a deployment model. Top files contain formulas and states. Formulas are independent and reusable entities and map to component types in EDMM. For example, one can create a Tomcat formula that encapsulates the logic to install and start a Tomcat web server. Further, a formula can define a set of configuration values that map to properties in EDMM. Moreover, a logical group of states defined in formulas are expressing operations which in turn relate to artifacts that implement these. Using their DSL syntax, arbitrary logic in the form of states can be supplied to reach a desired state. By using a formula in a deployment model a component is created according to our metamodel. Relations in SaltStack are, on the one hand, derived by the sequence of used formulas in a deployment model. On the other hand, states can depend on other stats defined by certain formulas, which results in a certain execution order.
Mapping to Juju
Juju is a topology-based application modeling tool based on a declarative YAML DSL. All instructions and artifacts necessary for deploying and configuring application components are defined in charms, which map to component types in the EDMM as they are reusable entities having a certain semantic. Each charm provides a set of configuration values that can be set during deployment, which are mapped to properties. Further, a charm defines actions, implemented as scripts, that are triggered by the runtime during deployment. These are respectively mapped to operations and artifacts, whereas artifacts that implement components are carried out by these operations. Charms can be used in bundles, which implies that a component of a certain component type inside a deployment model is used. In Juju, there can be relations following a “depends on” semantic by expressing requirements and capabilities on charms. For example, charm defines that it requires a database and, correspondingly, a database charm is capable of satisfying this requirements. This can be expressed using the relations keyword in the model. A compound deployment including multiple charms, their configuration, and relations can be described in a Juju bundle.
Mapping to Cloudify
The DSL defined and used by Cloudify is based on the TOSCA YAML profile [30]. However, the standard is not completely met. Similar to OpenStack Heat, built-in types encompassing Cloudify basic types can be used to model components. Further components types can be made available using plugins. In Cloudify, node types and node templates are mapped to component types and components respectively according to the EDMM definitions. Using Cloudify’s lifecycle interface, i.e., operations allow to create, start, stop, and terminate physical resources. Node types define properties, implement operations, and define deployment as well as implementation artifacts. Built-in relation types, for example, define a depends_on or connected_to relation between components. In contrast to all other considered technologies, further relation types can be defined. To realize the reference scenario from Fig. 1, the AWS and Azure plugins are required. These plugins provide all types, operations, and artifacts to model the required components as well as to interact with the respective cloud provider application-programming-interfaces (API).
EDMM to ProvS-technology mapping
We hereby show how the EDMM can be semantically mapped to AWS CloudFormation and Azure Resource Manager. In contrast to GP, these technologies only support single-cloud deployments as they only support the services of the respective cloud provider.
Mapping to AWS CloudFormation
AWS CloudFormation is the deployment and management service by AWS and uses a JSON or YAML templates to create deployment models. In the template, resources are used to express components. AWS provides a set of built-in resource types, referred as component types, that specify the semantics of components, e.g., defining properties supported by a resource. CloudFormation enables to create reusable component types by defining stacks that can be in turn used in other templates. Each stack of the reference scenario in Fig. 1 can be modeled by one or more resources. For example, the AWS SQS and Lambda service an be used to implement the depicted JMS 1.1 Queue and Order Worker components. To deploy the Admin App an AWS EC2 instance can be defined where one can specify the required installation and configuration steps as an operations, provided in separate files. The semantic of relations is restricted as only one type of inter-component dependency can be specified, by using the attribute dependsOn on resources.
Mapping to Azure Resource Manager
In Azure Resource Manager (ARM), JSON templates describe the configuration of Azure resources and services. Azure services (e.g., compute instances, databases, or middleware) are modeled as resources. The structure and semantics of a resource (e.g., its supported properties and artifacts) are defined by built-in resource types. Hence, resource and resource type map to component and component type in the EDMM. For example, the MongoDB configuration hosted on Azure Cosmos DB can be expressed using a resource of type Microsoft.DocumentDB/databaseAccounts. Relations between resources can be specified using the dependsOn element defining a dependency to one or more resources. The resources of a deployment can either be defined in a single template or divided into multiple ones in order to create purpose-specific, reusable templates. As ARM templates are logical and reusable units, they are mapped to components and component types in the EDMM. Post-deployment configurations, software installations, or other actions to configure a VM, can be achieved through virtual machine extensions, which are semantically mapped to operations in the EDMM.
EDMM to PlatS-technology mapping
We hereby show how the EDMM can be semantically mapped to Kubernetes, CFEngine, and Docker Compose. In contrast to GP, these technologies are restricted to specific services (XaaS support) and to the use of specific platform bundles for realizing components.
Mapping to Kubernetes
With Kubernetes, developers can specify the deployment model of a multi-service application by indicating the “pods” to run, one for each service forming the application. Their desired configuration can then be specified by defining “deployments”, each targeting a different subset of pods. For instance, each component in our reference application (cf. Fig. 1) should be placed in a different pod, and its desired configuration could be specified by defining a different deployment targeting its corresponding pod. Kubernetes hence provides a predefined set of component types allowing to define reusable units of pods, deployments, and services (components of an application). Kubernetes also supports a predefined set of relation types in the form of specifying which pods are targeted by which deployment or service. Attributes specifying the desired configuration for pods, deployments, and services are mapped to properties in the EDMM. In Kubernetes, artifacts for implementing components are reflected by container images, which contain the complete stack starting from the operating system to the application-specific component, depending on application requirements [35]. Moreover, container images also encapsulate operations representing the logic to install and configure the components. Therefore, container images are platform bundles as they are the unit of deployment.
Mapping to CFEngine
CFEngine assumes an already running computing infrastructure and, therefore, is assigned to the PlatS deployment technologies. In CFEngine, everything is a promise. Promises are used to define the desired state that should be reached, e.g., a package to be installed or a process to be started. Further, bundles can be used to logically group promises and are, therefore, mapped to operations in EDMM. Bodies are used to create reusable parts of promises and are mapped to component types. Bodies can also define properties and once they are used in a deployment model a concrete component is created. There can be explicit relations between components that specify the required execution order using the depends_on property on promises.
Mapping to Docker Compose
Docker Compose permits specifying the deployment model of a multi-container Docker application in a single file. The file is organized in “services”, which are used to specify the components (i.e., its containers) of an application. Relations between components are expressed using the depends_on keyword. Mapping this to our metamodel, the only component type and relation type are expressed by “services” and by the depends_on attribute, respectively. Docker Compose predefines the set of properties that can be associated with the services forming an application. Properties can be associated to each service in a Docker Compose file and specify the desired configuration. Artifacts and operations are a special case since they have to be packaged as a so-called platform bundle. The artifact implementing a component as well as the logic to install and configure it must be supplied through a Docker image, either retrieved from a repository or built based on a Dockerfile. For example, to deploy the Order App the complete stack starting from the operating system to the application-specific component must be linked into a Docker image.
EDMM to TOSCA
As various technologies support the TOSCA standard, i.e., OpenTOSCA [7], ALIEN 4 Cloud [1], Cloudify, and TosKer [10], this section presents a mapping of EDMM to TOSCA—although it was out of scope of this paper due to its rank. EDMM only uses a subset of entities specified by the standard: Service templates are used to express deployment models, while components and component types are referred as node templates and node types, respectively. TOSCA allows the definition of arbitrary relations and relation types, called relationship template and relationship type, but defines a certain set of normative types every compliant orchestrator needs to support, i.e., hosted_on and connected_to. Node types and relationship types support the definition of properties as they are used to define semantics. Further, operations in EDMM are mapped to management operations, which are realized by implementation artifacts. In contrast, there are deployment artifacts that are mapped to artifacts required for the execution of a component.