#  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.

Namespaces:
  =: io.murano.resources
  sys: io.murano.system
  std: io.murano

Name: HeatSWConfigInstance

Extends:
  - Instance

Methods:
  initialize:
    Body:
      - $.softwareConfigs: []

  # configName will be prepended with the instance name
  # configSection should be a map representing the 'config'
  #      fragment in a StructuredConfig
  # inputValues should be a map with any required inputs
  # signalTransport: null (==CFN_SIGNAL), HEAT_SIGNAL, NO_TRANSPORT
  #
  # A StructuredConfig and StructuredDeployment will be added
  # to the Instance
  addStructuredConfig:
    Arguments:
      - configName:
          Contract: $.string().notNull()
      - configSection:
          Contract: {}
      - inputValues:
          Contract: {}
          Default: {}
      - signalTransport:
          Contract: $.string()
          Default: null
    Body:
      - $group: Heat::Ungrouped
      - $.addSoftwareConfig($configName, $configSection,
                            inputValues=>$inputValues,
                            configGroup=>$group, isStructured=>True,
                            signalTransport=>$signalTransport)

  # Adds a SoftwareConfig and SoftwareDeployment.
  # configName will be prepended with the instance name
  # configSection should be of a suitable form (structured config takes maps,
  # ordinary software config can take a string or a map),
  # configGroup can be Heat::Ungrouped, script, puppet etc
  # inputValues should be a map with any inputs required by the Config
  # signalTransport: null (==CFN_SIGNAL), HEAT_SIGNAL, NO_TRANSPORT
  addSoftwareConfig:
    Arguments:
      - configName:
          Contract: $.string().notNull()
      - configSection:
          # Should be string unless for a structured config
          Contract: $.notNull()
      - inputValues:
          Contract: {}
          Default: {}
      - configGroup:
          Contract: $.string()
          Default: Heat::Ungrouped
      - isStructured:
          Contract: $.bool()
          Default: False
      - signalTransport:
          Contract: $.string()
          Default: null

    Body:
      - $full_config_name: $.name + '-' + $configName
      - $deployment_name: $full_config_name + '-deployment'
      - $deployment_stderr: $deployment_name + '-stderr'
      - $deployment_stdout: $deployment_name + '-stdout'
      - $injectConfig: $configSection
      - $configType: OS::Heat::SoftwareConfig
      - $deploymentType: OS::Heat::SoftwareDeployment
      - If: $isStructured
        Then:
         - $configType: OS::Heat::StructuredConfig
         - $deploymentType: OS::Heat::StructuredDeployment
         - $injectConfig['completion-signal']: {get_input: deploy_signal_id}
      - $fragment:
          resources:
            $full_config_name:
              type: $configType
              properties:
                group: $configGroup
                config:
                  $injectConfig
            $deployment_name:
              type: $deploymentType
              properties:
                config: { get_resource: $full_config_name }
                server: { get_resource: $.name }
                signal_transport: $signalTransport
                input_values:
                  $inputValues
          outputs:
            $deployment_stdout:
              value: {get_attr: [$deployment_name, deploy_stdout]}
            $deployment_stderr:
              value: {get_attr: [$deployment_name, deploy_stderr]}

      - $.softwareConfigs: $.softwareConfigs + list($fragment)
      - $.setAttr(scResources, $.getAttr(scResources, []).concat([$full_config_name, $deployment_name]))
      - $.setAttr(scOutputs, $.getAttr(scOutputs, []).concat([$deployment_stdout, $deployment_stderr]))

  # Adds to the stack any heat SW config elements
  prepareStackTemplate:
    Arguments:
      instanceTemplate:
        Contract: {}
    Body:
      - For: fragment
        In: $.softwareConfigs
        Do:
          - $instanceTemplate: $instanceTemplate.mergeWith($fragment)
      - Return: $instanceTemplate

  prepareUserData:
    Body:
      - Return:
          data:
          format: SOFTWARE_CONFIG

  releaseResources:
    Body:
      - $region: $.getRegion()
      - $template: $region.stack.current()
      - If: $template.get(resources) and $template.get(outputs)
        Then:
          - $template.resources: $template.resources.deleteAll($.getAttr(scResources, []))
          - $template.outputs: $template.outputs.deleteAll($.getAttr(scOutputs, []))
          - $region.stack.setTemplate($template)
      - super($, $.releaseResources())
      - $.setAttr(scResources, [])
      - $.setAttr(scOutputs, [])
