# ============LICENSE_START==========================================
# ===================================================================
# Copyright (c) 2017 AT&T
#
# 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.
#============LICENSE_END============================================

tosca_definitions_version: cloudify_dsl_1_3

description: >
  This blueprint creates a Kubernetes Cluster.
  It is based on this documentation: https://kubernetes.io/docs/getting-started-guides/kubeadm/

imports:
  - https://raw.githubusercontent.com/cloudify-cosmo/cloudify-manager/4.1/resources/rest-service/cloudify/types/types.yaml
  - https://raw.githubusercontent.com/cloudify-cosmo/cloudify-openstack-plugin/2.2.0/plugin.yaml
  - https://raw.githubusercontent.com/cloudify-incubator/cloudify-utilities-plugin/1.2.5/plugin.yaml
  - https://raw.githubusercontent.com/cloudify-cosmo/cloudify-fabric-plugin/1.5/plugin.yaml
  - https://raw.githubusercontent.com/cloudify-cosmo/cloudify-diamond-plugin/1.3.5/plugin.yaml
  - imports/cloud-config.yaml
  - imports/kubernetes.yaml

inputs:

  image:
    description: Image to be used when launching agent VMs
    default: { get_secret: centos_core_image }

  flavor:
    description: Flavor of the agent VMs
    default: { get_secret: large_image_flavor }

  agent_user:
    description: >
      User for connecting to agent VMs
    default: centos

  helm_version:
    description: helm version to be installed
    default: v2.9.1

dsl_definitions:

  openstack_config: &openstack_config
    username: { get_secret: keystone_username }
    password: { get_secret: keystone_password }
    tenant_name: { get_secret: keystone_tenant_name }
    auth_url: { get_secret: keystone_url }
    region: { get_secret: region }

node_templates:

  nfs_server:
    type: cloudify.nodes.SoftwareComponent
    properties:
    interfaces:
      cloudify.interfaces.lifecycle:
         start:
          implementation: fabric.fabric_plugin.tasks.run_script
          inputs:
            script_path: scripts/nfs.sh
            use_sudo: true
            process:
              args:
            fabric_env:
              host_string: { get_attribute: [ kubernetes_master_host, ip ] }
              user: { get_input: agent_user }
              key: { get_secret: agent_key_private }
    relationships:
      - type: cloudify.relationships.contained_in
        target: kubernetes_master_host

  k8s_tools:
    type: cloudify.nodes.SoftwareComponent
    properties:
    interfaces:
      cloudify.interfaces.lifecycle:
         start:
          implementation: fabric.fabric_plugin.tasks.run_script
          inputs:
            script_path: scripts/k8s_tools.sh
            process:
              args: [{ get_input: helm_version }]
            fabric_env:
              host_string: { get_attribute: [ kubernetes_master_host, ip ] }
              user: { get_input: agent_user }
              key: { get_secret: agent_key_private }
    relationships:
      - type: cloudify.relationships.contained_in
        target: kubernetes_master

  kubernetes_master_host:
    type: cloudify.openstack.nodes.Server
    properties:
      openstack_config: *openstack_config
      agent_config:
          user: { get_input: agent_user }
          install_method: remote
          port: 22
          key: { get_secret: agent_key_private }
      server:
        key_name: ''
        image: ''
        flavor: ''
      management_network_name: { get_property: [ public_network, resource_id ] }
    interfaces:
      cloudify.interfaces.lifecycle:
        create:
          inputs:
            args:
              image: { get_input: image }
              flavor: { get_input: flavor }
              userdata: { get_attribute: [ cloudify_host_cloud_config, cloud_config ] }
    relationships:
      - target: kubernetes_master_port
        type: cloudify.openstack.server_connected_to_port
      - type: cloudify.relationships.depends_on
        target: cloudify_host_cloud_config

  kubernetes_node_host:
    type: cloudify.openstack.nodes.Server
    properties:
      openstack_config: *openstack_config
      agent_config:
          user: { get_input: agent_user }
          install_method: remote
          port: 22
          key: { get_secret: agent_key_private }
      server:
        key_name: ''
        image: ''
        flavor: ''
      management_network_name: { get_property: [ private_network, resource_id ] }
    relationships:
      - type: cloudify.relationships.contained_in
        target: k8s_node_scaling_tier
      - target: kubernetes_node_port
        type: cloudify.openstack.server_connected_to_port
    interfaces:
      cloudify.interfaces.lifecycle:
        create:
          inputs:
            args:
              image: { get_input: image }
              flavor: { get_input: flavor }
              userdata: { get_attribute: [ cloudify_host_cloud_config, cloud_config ] }
      cloudify.interfaces.monitoring_agent:
          install:
            implementation: diamond.diamond_agent.tasks.install
            inputs:
              diamond_config:
                interval: 1
          start: diamond.diamond_agent.tasks.start
          stop: diamond.diamond_agent.tasks.stop
          uninstall: diamond.diamond_agent.tasks.uninstall
      cloudify.interfaces.monitoring:
          start:
            implementation: diamond.diamond_agent.tasks.add_collectors
            inputs:
              collectors_config:
                CPUCollector: {}
                MemoryCollector: {}
                LoadAverageCollector: {}
                DiskUsageCollector:
                  config:
                    devices: x?vd[a-z]+[0-9]*$
                NetworkCollector: {}
                ProcessResourcesCollector:
                  config:
                    enabled: true
                    unit: B
                    measure_collector_time: true
                    cpu_interval: 0.5
                    process:
                      hyperkube:
                        name: hyperkube

  kubernetes_security_group:
    type: cloudify.openstack.nodes.SecurityGroup
    properties:
      openstack_config: *openstack_config
      security_group:
        name: kubernetes_security_group
        description: kubernetes master security group
      rules:
      - remote_ip_prefix: 0.0.0.0/0
        port_range_min: 1
        port_range_max: 65535
        protocol: tcp
        direction: ingress
        ethertype: IPv4
      - remote_ip_prefix: 0.0.0.0/0
        port_range_min: 1
        port_range_max: 65535
        protocol: tcp
        direction: egress
        ethertype: IPv4
      - remote_ip_prefix: 0.0.0.0/0
        port_range_min: 1
        port_range_max: 65535
        protocol: udp
        direction: ingress
        ethertype: IPv4
      - remote_ip_prefix: 0.0.0.0/0
        port_range_min: 1
        port_range_max: 65535
        protocol: udp
        direction: egress
        ethertype: IPv4

  kubernetes_master_port:
    type: cloudify.openstack.nodes.Port
    properties:
      openstack_config: *openstack_config
    relationships:
      - type: cloudify.relationships.contained_in
        target: public_network
      - type: cloudify.relationships.depends_on
        target: public_subnet
      - type: cloudify.openstack.port_connected_to_security_group
        target: kubernetes_security_group
      - type: cloudify.openstack.port_connected_to_floating_ip
        target: kubernetes_master_ip

  kubernetes_node_port:
    type: cloudify.openstack.nodes.Port
    properties:
      openstack_config: *openstack_config
    relationships:
      - type: cloudify.relationships.contained_in
        target: k8s_node_scaling_tier
      - type: cloudify.relationships.connected_to
        target: private_network
      - type: cloudify.relationships.depends_on
        target: private_subnet
      - type: cloudify.openstack.port_connected_to_security_group
        target: kubernetes_security_group

  private_subnet:
    type: cloudify.openstack.nodes.Subnet
    properties:
      openstack_config: *openstack_config
      use_external_resource: true
      resource_id: { get_secret: private_subnet_name }
    relationships:
      - target: private_network
        type: cloudify.relationships.contained_in

  private_network:
    type: cloudify.openstack.nodes.Network
    properties:
      openstack_config: *openstack_config
      use_external_resource: true
      resource_id: { get_secret: private_network_name }

  public_subnet:
    type: cloudify.openstack.nodes.Subnet
    properties:
      openstack_config: *openstack_config
      use_external_resource: true
      resource_id: { get_secret: public_subnet_name }
    relationships:
      - target: public_network
        type: cloudify.relationships.contained_in
      - target: router
        type: cloudify.openstack.subnet_connected_to_router

  public_network:
    type: cloudify.openstack.nodes.Network
    properties:
      openstack_config: *openstack_config
      use_external_resource: true
      resource_id: { get_secret: public_network_name }

  router:
    type: cloudify.openstack.nodes.Router
    properties:
      openstack_config: *openstack_config
      use_external_resource: true
      resource_id: { get_secret: router_name }
    relationships:
      - target: external_network
        type: cloudify.relationships.connected_to

  external_network:
    type: cloudify.openstack.nodes.Network
    properties:
      openstack_config: *openstack_config
      use_external_resource: true
      resource_id: { get_secret: external_network_name }

  k8s_node_scaling_tier:
    type: cloudify.nodes.Root

  kubernetes_master_ip:
    type: cloudify.openstack.nodes.FloatingIP
    properties:
      openstack_config: *openstack_config
      floatingip:
        floating_network_name: { get_property: [ external_network, resource_id ] }

groups:

  k8s_node_group:
    members:
      - kubernetes_node_host
      - kubernetes_node_port

policies:

  kubernetes_node_vms_scaling_policy:
    type: cloudify.policies.scaling
    properties:
      default_instances: 6
    targets: [k8s_node_group]

outputs:

  kubernetes_master_public_ip:
    value: { get_attribute: [ kubernetes_master_ip, floating_ip_address ] }