---
- name: Kubernetes Master | register kube-apiserver
  blockinfile:
    path: /etc/systemd/system/kube-apiserver.service
    create: yes
    block: |
      [Unit]
      Description=Kubernetes API Server
      Documentation=https://github.com/GoogleCloudPlatform/kubernetes
      [Service]
      ExecStart=/usr/bin/kube-apiserver \
        --bind-address=0.0.0.0 \
        --service-cluster-ip-range={{ kubernetes_cluster_info.SERVICE_CLUSTER_IP_RANGE }} \
        --address=0.0.0.0 \
        --etcd-servers=http://127.0.0.1:2379 \
        --v=2 \
        --insecure-bind-address={{ host_public_ip }} \
        --allow-privileged=true \
        --anonymous-auth=false \
        --secure-port=443 \
        --advertise-address={{ host_internal_ip }} \
        --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
        --tls-cert-file={{ kubernetes_certificates.directory }}/apiserver.pem \
        --tls-private-key-file={{ kubernetes_certificates.directory }}/apiserver-key.pem \
        --client-ca-file={{ kubernetes_certificates.directory }}/ca.pem \
        --service-account-key-file={{ kubernetes_certificates.directory }}/apiserver-key.pem \
        --runtime-config=extensions/v1beta1=true,extensions/v1beta1/networkpolicies=true,batch/v2alpha1=true
      Restart=on-failure
      RestartSec=10
      WorkingDirectory=/root/
      [Install]
      WantedBy=multi-user.target

- name: Kubernetes Master | register kube-controller-manager
  blockinfile:
    path: /etc/systemd/system/kube-controller-manager.service
    create: yes
    block: |
      [Unit]
      Description=Kubernetes Controller Manager
      Documentation=https://github.com/GoogleCloudPlatform/kubernetes
      [Service]
      ExecStart=/usr/bin/kube-controller-manager \
        --master={{ host_public_ip }}:8080 \
        --v=2 \
        --cluster-cidr={{ kubernetes_cluster_info.CLUSTER_SUBNET }} \
        --service-account-private-key-file={{ kubernetes_certificates.directory }}/apiserver-key.pem \
        --root-ca-file={{ kubernetes_certificates.directory }}/ca.pem \
        --cluster-signing-cert-file={{ kubernetes_certificates.directory }}/ca.pem \
        --cluster-signing-key-file={{ kubernetes_certificates.directory }}/ca-key.pem
      Restart=on-failure
      RestartSec=10
      [Install]
      WantedBy=multi-user.target

- name: Kubernetes Master | register kube-scheduler
  blockinfile:
    path: /etc/systemd/system/kube-scheduler.service
    create: yes
    block: |
      [Unit]
      Description=Kubernetes Scheduler
      Documentation=https://github.com/GoogleCloudPlatform/kubernetes
      [Service]
      ExecStart=/usr/bin/kube-scheduler \
        --master={{ host_public_ip }}:8080 \
        --v=2 \
        --leader-elect=true
      Restart=on-failure
      RestartSec=10
      [Install]
      WantedBy=multi-user.target

- name: Kubernetes Master | register etcd3
  blockinfile:
    path: /etc/systemd/system/etcd3.service
    create: yes
    block: |
      [Unit]
      Description=Etcd store
      Documentation=https://github.com/coreos/etcd
      [Service]
      ExecStartPre=-/usr/bin/docker rm -f etcd
      ExecStart=/usr/bin/docker run --name etcd \
        --net=host \
        --volume /var/etcd:/var/etcd \
        quay.io/coreos/etcd:v{{ kubernetes_cluster_info.ETCD_VERSION }} \
          /usr/local/bin/etcd \
          --data-dir /var/etcd/data
      Restart=on-failure
      RestartSec=10
      [Install]
      WantedBy=multi-user.target

- name: Kubernetes Master | Assume that the certs were not generated now
  set_fact:
    certs_generated: false

- name: Kubernetes Master | Check if all the certs are present
  block:
    - stat:
        path: "{{ kubernetes_certificates.directory }}/ca.pem"
      register: ca_cert

    - stat:
        path: "{{ kubernetes_certificates.directory }}/ca-key.pem"
      register: ca_cert_key

    - stat:
        path: "{{ kubernetes_certificates.directory }}/apiserver.pem"
      register: apiserver_cert

    - stat:
        path: "{{ kubernetes_certificates.directory }}/apiserver-key.pem"
      register: apiserver_cert_key

    - stat:
        path: "{{ kubernetes_certificates.directory }}/admin.pem"
      register: admin_cert

    - stat:
        path: "{{ kubernetes_certificates.directory }}/admin-key.pem"
      register: admin_cert_key

- name: Kubernetes Master | Generate certs if needed
  block:
    - include_tasks: ./generate_certs_master.yml

    - set_fact:
        certs_generated: true
  when: (not ca_cert.stat.exists or
         not ca_cert_key.stat.exists or
         not apiserver_cert.stat.exists or
         not apiserver_cert_key.stat.exists or
         not admin_cert.stat.exists or
         not admin_cert_key.stat.exists)

- name: Kubernetes Master | Fetching certificates on the ansible host
  synchronize:
    mode: pull
    src: "{{ kubernetes_certificates.directory }}/{{ item }}"
    dest: "{{ ansible_tmp_dir }}/k8s_{{ item }}"
    use_ssh_args: yes
  with_items:
    - ca.pem
    - ca-key.pem

- name: Kubernetes Master | restart all services
  service:
    name: "{{item}}"
    enabled: yes
    state: restarted
    daemon_reload: yes
  with_items:
    - etcd3
    - kube-apiserver
    - kube-controller-manager
    - kube-scheduler
  changed_when: false

- name: Kubernetes Master | Setting kubectl context
  shell: |
    set -o errexit
    kubectl config set-cluster default-cluster --server=https://{{ host_public_ip }} --certificate-authority={{ kubernetes_certificates.directory }}/ca.pem
    kubectl config set-credentials default-admin --certificate-authority={{ kubernetes_certificates.directory }}/ca.pem --client-key={{ kubernetes_certificates.directory }}/admin-key.pem --client-certificate={{ kubernetes_certificates.directory }}/admin.pem
    kubectl config set-context local --cluster=default-cluster --user=default-admin
    kubectl config use-context local
  changed_when: false

- name: Kubernetes Master | Waiting for kube-apiserver to start
  block:
    - name: Kubernetes Master | Running kubectl version
      shell: kubectl version
      changed_when: false
      register: kubeapiserver_ready
      until: kubeapiserver_ready.rc == 0
      retries: 30
      delay: 3
  rescue:
    - fail:
        msg: Kubernetes API server could not reach ready status, check the service log

- name: Kubernetes Master | Fetch Token
  shell: kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t'
  changed_when: false
  register: fetch_token
  until: fetch_token.stdout | trim != ""
  retries: 10
  delay: 3

- name: Kubernetes Master | Register Token
  set_fact:
    TOKEN: "{{fetch_token.stdout | trim}}"

- name: Kubernetes Master | Checking Token
  fail:
      msg: Could not fetch Token, make sure kubectl can connect to the API server
  when: TOKEN == ""

- name: Kubernetes Master | Create service OVN Kube
  blockinfile:
    path: /etc/systemd/system/ovn-kubernetes-master.service
    create: yes
    block: |
      [Unit]
      Description=OVN watches the Kubernetes API
      Documentation=https://github.com/ovn-org/ovn-kubernetes#watchers-on-master-node
      [Service]
      ExecStart=/usr/bin/ovnkube \
        -init-master "{{ ansible_hostname }}" \
        -cluster-subnets "{{ kubernetes_cluster_info.CLUSTER_SUBNET }}" \
        -k8s-service-cidr "{{ kubernetes_cluster_info.SERVICE_CLUSTER_IP_RANGE }}" \
        -nodeport \
        -k8s-token {{TOKEN}} \
        -k8s-cacert /etc/openvswitch/k8s-ca.crt \
        -k8s-apiserver "https://{{ host_public_ip }}" \
        -nb-address tcp://127.0.0.1:6641 \
        -sb-address tcp://127.0.0.1:6642
      Restart=on-failure
      RestartSec=10
      WorkingDirectory=/root/
      [Install]
      WantedBy=multi-user.target

- name: Kubernetes Master | Ensure /etc/hosts is updated
  lineinfile:
    path: /etc/hosts
    line: "{{ host_public_ip }} {{ ansible_hostname }}"

- name: Kubernetes Master | Enabling OVN to listen on 6641 and 6642
  shell: |
    set -o errexit
    ovn-nbctl --timeout={{TIMEOUT}} set-connection ptcp:6641
    ovn-sbctl --timeout={{TIMEOUT}} set-connection ptcp:6642
  changed_when: false

- name: Kubernetes Master | Setting OVN external_ids
  shell: |
    ovs-vsctl --timeout={{TIMEOUT}} set Open_vSwitch . external_ids:ovn-remote="tcp:{{ host_public_ip }}:6642" \
      external_ids:ovn-nb="tcp:{{ host_public_ip }}:6641" \
      external_ids:ovn-encap-ip="{{ host_internal_ip }}" \
      external_ids:ovn-encap-type="geneve"
  changed_when: false

# TODO: enable this for future GCE support in the playbooks
# - name: Kubernetes Master | Setting OVN external_ids when GCE
#   shell: |
#     ovs-vsctl set Open_vSwitch . external_ids:ovn-encap-ip="{{ host_public_ip }}"
#   when: GCE

- name: Kubernetes Master | Prepare OVN certs
  shell: |
    set -o errexit
    ovs-vsctl --timeout={{TIMEOUT}} set Open_vSwitch . \
      external_ids:k8s-api-server="https://{{ host_public_ip }}" \
      external_ids:k8s-api-token="{{TOKEN}}"
    ln -fs {{ kubernetes_certificates.directory }}/ca.pem /etc/openvswitch/k8s-ca.crt
  changed_when: false

- name: Kubernetes Master | restart ovn-kubernetes-master
  service:
    name: "ovn-kubernetes-master"
    enabled: yes
    state: restarted
    daemon_reload: yes
  changed_when: false

- name: Kubernetes Master | Create test yamls
  blockinfile:
    path: /root/apache-pod.yaml
    create: yes
    marker: "# {mark} Ansible automatic example generation"
    block: |
      apiVersion: v1
      kind: Pod
      metadata:
        name: apachetwin
        labels:
          name: webserver
      spec:
        containers:
        - name: apachetwin
          image: fedora/apache
        nodeSelector:
          kubernetes.io/os: linux
- name: Create test yamls
  blockinfile:
    path: /root/apache-e-w.yaml
    create: yes
    marker: "# {mark} Ansible automatic example generation"
    block: |
      apiVersion: v1
      kind: Service
      metadata:
        labels:
          name: apacheservice
          role: service
        name: apacheservice
      spec:
        ports:
          - port: 8800
            targetPort: 80
            protocol: TCP
            name: tcp
        selector:
          name: webserver
- name: Create test yamls
  blockinfile:
    path: /root/apache-n-s.yaml
    create: yes
    marker: "# {mark} Ansible automatic example generation"
    block: |
      apiVersion: v1
      kind: Service
      metadata:
        labels:
          name: apacheexternal
          role: service
        name: apacheexternal
      spec:
        ports:
          - port: 8800
            targetPort: 80
            protocol: TCP
            name: tcp
        selector:
          name: webserver
        type: NodePort
- name: Create test yamls
  blockinfile:
    path: /root/nginx-pod.yaml
    create: yes
    marker: "# {mark} Ansible automatic example generation"
    block: |
      apiVersion: v1
      kind: Pod
      metadata:
        name: nginxtwin
        labels:
          name: webserver
      spec:
        containers:
        - name: nginxtwin
          image: nginx
        nodeSelector:
          kubernetes.io/os: linux
