---
- block:
    - set_fact:
        scale_namespace: "{{ test_namespace }}"

    - name: Add a deployment
      k8s:
        definition:
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: scale-deploy
            namespace: "{{ scale_namespace }}"
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: "{{ k8s_pod_name }}"
            template: "{{ k8s_pod_template }}"
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
        apply: yes
      vars:
        k8s_pod_name: scale-deploy
        k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
        k8s_pod_ports:
          - containerPort: 8080
            name: http
            protocol: TCP

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        namespace: "{{ scale_namespace }}"
        field_selectors:
          - status.phase=Running

    - name: Scale the deployment (check_mode)
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 0
        wait: yes
      register: scale_down
      check_mode: true

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        namespace: "{{ scale_namespace }}"
        field_selectors:
          - status.phase=Running
      register: scale_down_deploy_pods
      ignore_errors: true
      until: scale_down_deploy_pods.resources | length == 0
      retries: 6
      delay: 5

    - name: Ensure the deployment did not changed and pods are still running
      assert:
        that:
          - scale_down is changed
          - scale_down_deploy_pods.resources | length > 0

    - name: Scale the deployment (check_mode) once again - validate idempotency
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 0
        wait: yes
      register: scale_down
      check_mode: true

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        namespace: "{{ scale_namespace }}"
        field_selectors:
          - status.phase=Running
      register: scale_down_deploy_pods
      ignore_errors: true
      until: scale_down_deploy_pods.resources | length == 0
      retries: 6
      delay: 5

    - name: Ensure the deployment did not changed and pods are still running
      assert:
        that:
          - scale_down is changed
          - scale_down_deploy_pods.resources | length > 0

    - name: Scale the deployment
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 0
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
      register: scale_down
      diff: true

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        namespace: "{{ scale_namespace }}"
        field_selectors:
          - status.phase=Running
      register: scale_down_deploy_pods
      until: scale_down_deploy_pods.resources | length == 0
      retries: 6
      delay: 5

    - name: Ensure that scale down took effect
      assert:
        that:
          - scale_down is changed
          - '"duration" in scale_down'
          - scale_down.diff

    - name: Scale the deployment once again (idempotency)
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 0
        wait: yes
      register: scale_down_idempotency
      diff: true

    - name: Ensure that scale down did not took effect
      assert:
        that:
          - scale_down_idempotency is not changed

    - name: Reapply the earlier deployment
      k8s:
        definition:
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: scale-deploy
            namespace: "{{ scale_namespace }}"
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: "{{ k8s_pod_name }}"
            template: "{{ k8s_pod_template }}"
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
        apply: yes
      vars:
        k8s_pod_name: scale-deploy
        k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
        k8s_pod_ports:
          - containerPort: 8080
            name: http
            protocol: TCP
      register: reapply_after_scale

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        namespace: "{{ scale_namespace }}"
        field_selectors:
          - status.phase=Running
      register: scale_up_deploy_pods

    - name: Ensure that reapply after scale worked
      assert:
        that:
          - reapply_after_scale is changed
          - scale_up_deploy_pods.resources | length == 1

    - name: Scale the deployment up
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 2
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
      register: scale_up
      diff: no

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        field_selectors:
          - status.phase=Running
        namespace: "{{ scale_namespace }}"
      register: scale_up_further_deploy_pods

    - name: Ensure that scale up worked
      assert:
        that:
          - scale_up is changed
          - '"duration" in scale_up'
          - scale_up.diff is not defined
          - scale_up_further_deploy_pods.resources | length == 2

    - name: Don't scale the deployment up
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 2
        wait: yes
      register: scale_up_noop
      diff: no

    - name: Get pods in scale-deploy
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        field_selectors:
          - status.phase=Running
        namespace: "{{ scale_namespace }}"
      register: scale_up_noop_pods

    - name: Ensure that no-op scale up worked
      assert:
        that:
          - scale_up_noop is not changed
          - scale_up_noop.diff is not defined
          - scale_up_noop_pods.resources | length == 2
          - '"duration" in scale_up_noop'

    - name: Scale deployment down without wait
      k8s_scale:
        api_version: apps/v1
        kind: Deployment
        name: scale-deploy
        namespace: "{{ scale_namespace }}"
        replicas: 1
        wait: no
      register: scale_down_no_wait
      diff: true

    - name: Ensure that scale down succeeds
      k8s_info:
        kind: Pod
        label_selectors:
          - app=scale-deploy
        namespace: "{{ scale_namespace }}"
      register: scale_down_no_wait_pods
      retries: 6
      delay: 5
      until: scale_down_no_wait_pods.resources | length == 1

    - name: Ensure that scale down without wait worked
      assert:
        that:
          - scale_down_no_wait is changed
          - scale_down_no_wait.diff
          - scale_down_no_wait_pods.resources | length == 1

    # scale multiple resource using label selectors
    - name: create deployment
      kubernetes.core.k8s:
        namespace: "{{ scale_namespace }}"
        src: files/deployment.yaml

    - name: list deployment
      kubernetes.core.k8s_info:
        kind: Deployment
        namespace: "{{ scale_namespace }}"
        label_selectors:
          - app=nginx
      register: resource
    - assert:
        that:
          - resource.resources | list | length == 2

    - name: scale deployment using resource version
      kubernetes.core.k8s_scale:
        replicas: 2
        kind: Deployment
        namespace: "{{ scale_namespace }}"
        resource_version: 0
        label_selectors:
          - app=nginx
      register: scale_out

    - assert:
        that:
          - not scale_out.changed
          - scale_out.results | selectattr('warning', 'defined') | list | length == 2

    - name: scale deployment using current replicas (wrong value)
      kubernetes.core.k8s_scale:
        replicas: 2
        current_replicas: 4
        kind: Deployment
        namespace: "{{ scale_namespace }}"
        label_selectors:
          - app=nginx
      register: scale_out

    - assert:
        that:
          - not scale_out.changed
          - scale_out.results | selectattr('warning', 'defined') | list | length == 2

    - name: scale deployment using current replicas (right value)
      kubernetes.core.k8s_scale:
        replicas: 2
        current_replicas: 3
        kind: Deployment
        namespace: "{{ scale_namespace }}"
        label_selectors:
          - app=nginx
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
      register: scale_out

    - assert:
        that:
          - scale_out.changed
          - scale_out.results | map(attribute='result.status.replicas') | list | unique == [2]

    - name: Create a StatefulSet
      kubernetes.core.k8s:
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
        definition:
          apiVersion: apps/v1
          kind: StatefulSet
          metadata:
            namespace: "{{ scale_namespace }}"
            name: scale-set
          spec:
            replicas: 2
            selector:
              matchLabels:
                app: foo
            template:
              metadata:
                labels:
                  app: foo
              spec:
                terminationGracePeriodSeconds: 10
                containers:
                  - image: busybox
                    name: busybox
                    command:
                      - sleep
                      - "600"
      register: output

    - assert:
        that:
          - output.result.status.replicas == 2

    - name: Wait for StatefulSet to scale down to 0
      kubernetes.core.k8s_scale:
        kind: StatefulSet
        api_version: apps/v1
        name: scale-set
        namespace: "{{ scale_namespace }}"
        replicas: 0
        wait: yes
        wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
      register: output

    - assert:
        that:
          - output.result.status.replicas == 0

  always:
    - name: Remove namespace
      k8s:
        kind: Namespace
        name: "{{ scale_namespace }}"
        state: absent
      ignore_errors: true
