Namespaces:
  =: io.murano.applications
  res: io.murano.resources
  std: io.murano

--- # ------------------------------------------------------------------ # ---
# A base class for applications running a single software component on a single
# server only

Name: SingleServerApplication
Extends:
  - std:Application
  - SoftwareComponent

Properties:
  server:
    Contract: $.class(res:Instance).notNull()

  # this is "private output" property. It is not part of the class interface
  # and should not be used from outside or by inheritors. It may be removed in
  # future in favor of attributes
  _serverGroup:
    Usage: Out
    Contract: $.class(SingleServerGroup)

Methods:
  .init:
    Body:
      - If: not $this._serverGroup
        Then:
          - $this._serverGroup: new(SingleServerGroup, $this, server => $this.server)
        Else:
          - If: $this.server != $this._serverGroup.server
            Then:
              - $this._serverGroup.setServer($this.server)
  deploy:
    Body:
      - $this.deployAt($this._serverGroup)

--- # ------------------------------------------------------------------ # ---
# A base class for applications running a single software component on multiple
# servers

Name: MultiServerApplication
Extends:
  - std:Application
  - SoftwareComponent

Properties:
  servers:
    Contract: $.class(ServerGroup).notNull()

Methods:
  deploy:
    Body:
      - $this.deployAt($this.servers)

--- # ------------------------------------------------------------------ # ---
# A base class for applications running a single software component on multiple
# servers which should support scale-out and scale-in scenarios

Name: MultiServerApplicationWithScaling
Extends: MultiServerApplication

Properties:
  servers:
    Contract: $.class(ServerReplicationGroup).notNull()

  scaleFactor:
    Contract: $.int().check($ > 0)
    Default: 1


Methods:
  scaleOut:
    Scope: Public
    Body:
      - $this.servers.scale($this.scaleFactor)
      - $this.deploy()

  scaleIn:
    Scope: Public
    Body:
      - $this.servers.scale(-1 * $this.scaleFactor)
      - $this.deploy()
