From e7ed329bd81c2273c03e94c93c9ce9c1d01cdc86 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Sat, 1 Apr 2017 04:53:28 +0200 Subject: Initial import --- roles/ands_kaas/defaults/main.yml | 11 ++ roles/ands_kaas/tasks/file.yml | 9 ++ roles/ands_kaas/tasks/keys.yml | 37 ++++++ roles/ands_kaas/tasks/main.yml | 12 ++ roles/ands_kaas/tasks/oc.yml | 10 ++ roles/ands_kaas/tasks/ocitem.yml | 13 ++ roles/ands_kaas/tasks/ocscript.yml | 8 ++ roles/ands_kaas/tasks/project.yml | 76 +++++++++++ roles/ands_kaas/tasks/sync.yml | 8 ++ roles/ands_kaas/tasks/sync_all.yml | 13 ++ roles/ands_kaas/tasks/template.yml | 17 +++ roles/ands_kaas/tasks/templates.yml | 20 +++ roles/ands_kaas/tasks/volume.yml | 11 ++ roles/ands_kaas/templates/0-gfs-volumes.yml.j2 | 38 ++++++ roles/ands_kaas/templates/6-kaas-pods.yml.j2 | 173 +++++++++++++++++++++++++ 15 files changed, 456 insertions(+) create mode 100644 roles/ands_kaas/defaults/main.yml create mode 100644 roles/ands_kaas/tasks/file.yml create mode 100644 roles/ands_kaas/tasks/keys.yml create mode 100644 roles/ands_kaas/tasks/main.yml create mode 100644 roles/ands_kaas/tasks/oc.yml create mode 100644 roles/ands_kaas/tasks/ocitem.yml create mode 100644 roles/ands_kaas/tasks/ocscript.yml create mode 100644 roles/ands_kaas/tasks/project.yml create mode 100644 roles/ands_kaas/tasks/sync.yml create mode 100644 roles/ands_kaas/tasks/sync_all.yml create mode 100644 roles/ands_kaas/tasks/template.yml create mode 100644 roles/ands_kaas/tasks/templates.yml create mode 100644 roles/ands_kaas/tasks/volume.yml create mode 100644 roles/ands_kaas/templates/0-gfs-volumes.yml.j2 create mode 100644 roles/ands_kaas/templates/6-kaas-pods.yml.j2 (limited to 'roles/ands_kaas') diff --git a/roles/ands_kaas/defaults/main.yml b/roles/ands_kaas/defaults/main.yml new file mode 100644 index 0000000..3835453 --- /dev/null +++ b/roles/ands_kaas/defaults/main.yml @@ -0,0 +1,11 @@ +kaas_resync: false +kaas_projects: "{{ ands_openshift_projects.keys() }}" + +kaas_template_root: "{{ ands_paths.provision }}/kaas/" + +kaas_glusterfs_endpoints: gfs +kaas_openshift_volumes: "{{ ands_openshift_volumes }}" + +kaas_default_volume_capacity: "1Ti" +kaas_default_file_owner: root +kaas_default_file_group: root diff --git a/roles/ands_kaas/tasks/file.yml b/roles/ands_kaas/tasks/file.yml new file mode 100644 index 0000000..9a36e74 --- /dev/null +++ b/roles/ands_kaas/tasks/file.yml @@ -0,0 +1,9 @@ +--- +- name: "Setting up files in {{ path }}" + file: + path: "{{ path }}" + recurse: "{{ file.recurse | default(true) }}" + mode: "{{ file.mode | default( ((file.state | default('directory')) == 'directory') | ternary('0755', '0644') ) }}" + owner: "{{ file.owner | default(kaas_project_config.file_owner) | default(kaas_default_file_owner) }}" + group: "{{ file.group | default(kaas_project_config.file_group) | default(kaas_default_file_group) }}" + state: "{{ file.state | default('directory') }}" diff --git a/roles/ands_kaas/tasks/keys.yml b/roles/ands_kaas/tasks/keys.yml new file mode 100644 index 0000000..2096c75 --- /dev/null +++ b/roles/ands_kaas/tasks/keys.yml @@ -0,0 +1,37 @@ +--- +- name: Try to locate pubkey file + set_fact: "kaas_{{ pod.key }}_pubkey={{ lookup('file', item) }}" + with_first_found: + - paths: + - "{{ kaas_project_path }}/keys/" + files: + - "{{ pod.key }}.crt" + - "{{ pod.key }}.pub" + - "{{ pod.value.service.host | default('default') }}.crt" + - "{{ pod.value.service.host | default('default') }}.pub" + skip: true + +- name: Try to locate privkey file + set_fact: "kaas_{{ pod.key }}_privkey={{ lookup('file', item) }}" + with_first_found: + - paths: + - "{{ kaas_project_path }}/keys/" + files: + - "{{ pod.key }}.key" + - "{{ pod.key }}.pem" + - "{{ pod.value.service.host | default('default') }}.key" + - "{{ pod.value.service.host | default('default') }}.pem" + skip: true + +- name: Try to locate CA file + set_fact: "kaas_{{ pod.key }}_ca={{ lookup('file', item) }}" + with_first_found: + - paths: + - "{{ kaas_project_path }}/keys/" + files: + - "{{ pod.key }}.ca" + - "{{ pod.value.service.host | default('default') }}.ca" + - ca-bundle.pem + - ca.pem + - ca.crt + skip: true diff --git a/roles/ands_kaas/tasks/main.yml b/roles/ands_kaas/tasks/main.yml new file mode 100644 index 0000000..c9fb857 --- /dev/null +++ b/roles/ands_kaas/tasks/main.yml @@ -0,0 +1,12 @@ +--- +- name: Provision OpenShift resources & configurations +# include: only_templates.yml + include: project.yml + run_once: true + delegate_to: "{{ groups.masters[0] }}" + with_items: "{{ kaas_projects }}" + loop_control: + loop_var: kaas_project + vars: + kaas_template_path: "{{ kaas_template_root }}/{{ kaas_project }}" + kaas_project_path: "{{playbook_dir}}/projects/{{ kaas_project }}" diff --git a/roles/ands_kaas/tasks/oc.yml b/roles/ands_kaas/tasks/oc.yml new file mode 100644 index 0000000..d3504f8 --- /dev/null +++ b/roles/ands_kaas/tasks/oc.yml @@ -0,0 +1,10 @@ +--- +- name: Configure KaaS resources + include_role: + name: openshift_resource + tasks_from: command.yml + vars: + resource: "{{ ocitem.resource | default('') }}" + command: "{{ ocitem.oc }}" + project: "{{ kaas_project }}" + recreate: "{{ ocitem.recreate | default(false) }}" diff --git a/roles/ands_kaas/tasks/ocitem.yml b/roles/ands_kaas/tasks/ocitem.yml new file mode 100644 index 0000000..f21e8cd --- /dev/null +++ b/roles/ands_kaas/tasks/ocitem.yml @@ -0,0 +1,13 @@ +--- +- name: OpenShift templates + include: templates.yml + run_once: true + vars: + kaas_template_glob: "{{ ocitem.template }}" + when: ocitem.template is defined + +- name: OpenShift commands + include: oc.yml + delegate_to: "{{ groups.masters[0] }}" + run_once: true + when: ocitem.oc is defined diff --git a/roles/ands_kaas/tasks/ocscript.yml b/roles/ands_kaas/tasks/ocscript.yml new file mode 100644 index 0000000..4927de4 --- /dev/null +++ b/roles/ands_kaas/tasks/ocscript.yml @@ -0,0 +1,8 @@ +--- +- include: ocitem.yml + delegate_to: "{{ groups.masters[0] }}" + run_once: true + with_items: "{{ kaas_project_config.oc }}" + loop_control: + loop_var: ocitem + \ No newline at end of file diff --git a/roles/ands_kaas/tasks/project.yml b/roles/ands_kaas/tasks/project.yml new file mode 100644 index 0000000..002596b --- /dev/null +++ b/roles/ands_kaas/tasks/project.yml @@ -0,0 +1,76 @@ +--- +- name: Load global variables + include_vars: "{{kaas_project_path}}/vars/globals.yml" + when: "'{{kaas_project_path}}/vars/globals.yml' | is_file" + +- name: Load variables + include_vars: dir="{{kaas_project_path}}/vars" name="kaas_project_config" + when: "'{{kaas_project_path}}/vars' | is_dir" + +- name: Ensure OpenShift template directory exists + file: path="{{ kaas_template_path }}" state="directory" mode=0755 owner=root group=root + +- name: Configure KaaS volumes + include: volume.yml + run_once: true + delegate_to: "{{ groups.masters[0] }}" + with_dict: "{{ kaas_project_config.volumes | default(kaas_openshift_volumes) }}" + loop_control: + loop_var: osv + vars: + query: "[*].volumes.{{osv.value.volume}}.mount" + mntpath: "{{ (ands_storage_domains | json_query(query)) }}" + path: "{{ mntpath[0] ~ (osv.value.path | default('')) }}" + name: "{{osv.key}}" + volume: "{{osv.value}}" + when: ( mntpath | length ) > 0 + +- name: Copy static configuration + include: sync_all.yml + run_once: true + delegate_to: "{{ groups.masters[0] }}" + with_items: "{{ lookup('pipe', search).split('\n') }}" + loop_control: + loop_var: osv_path + vars: + search: "find {{ kaas_project_path }}/files/ -type d -mindepth 1 -maxdepth 1" + osv: "{{ osv_path | basename }}" + pvar: "kaas_{{ osv }}_path" + local_path: "{{ osv_path }}" + remote_path: "{{ hostvars[inventory_hostname][pvar] }}" + when: + - osv in kaas_openshift_volumes + - hostvars[inventory_hostname][pvar] is defined + +- name: Configure KaaS files + include: file.yml + run_once: true + delegate_to: "{{ groups.masters[0] }}" + with_items: "{{ kaas_project_config.files | default(ands_openshift_files) }}" + loop_control: + loop_var: file + vars: + pvar: "kaas_{{ file.osv }}_path" + path: "{{ hostvars[inventory_hostname][pvar] }}/{{ file.path }}" + when: file.osv in ( kaas_project_config.volumes | default(kaas_openshift_volumes) ) + +- name: Load OpenSSL keys + include: keys.yml + delegate_to: "{{ groups.masters[0] }}" + run_once: true + with_dict: "{{ kaas_project_config.pods }}" + loop_control: + loop_var: pod + +- name: "Run OC script" + include: ocscript.yml + delegate_to: "{{ groups.masters[0] }}" + run_once: true + when: kaas_project_config.oc is defined + +- name: "Configure all templates" + include: templates.yml + delegate_to: "{{ groups.masters[0] }}" + run_once: true + when: kaas_project_config.oc is undefined + diff --git a/roles/ands_kaas/tasks/sync.yml b/roles/ands_kaas/tasks/sync.yml new file mode 100644 index 0000000..399cb66 --- /dev/null +++ b/roles/ands_kaas/tasks/sync.yml @@ -0,0 +1,8 @@ +--- +- name: Check if already exists + stat: path="{{ item_dest }}" + register: result + +- name: "Sync '{{ item_name }}'" + synchronize: src="{{ item_src }}" dest="{{ remote_path }}/" archive=yes + when: (result.stat.exists == False) or (kaas_resync | default(false)) diff --git a/roles/ands_kaas/tasks/sync_all.yml b/roles/ands_kaas/tasks/sync_all.yml new file mode 100644 index 0000000..58a1710 --- /dev/null +++ b/roles/ands_kaas/tasks/sync_all.yml @@ -0,0 +1,13 @@ +# If delegation is enabled, synchronize will look from files on delegated host not locally + +- name: "Analyze '{{ local_path | basename }}'" +# debug: msg="{{ local_path }} - {{ item_name }} - {{ item }}" + include: sync.yml + run_once: true + with_items: "{{ lookup('pipe', filesearch).split('\n') }}" + vars: + filesearch: "find '{{ local_path }}' -mindepth 1 -maxdepth 1" + item_name: "{{ item | basename }}" + item_src: "{{ local_path }}/{{ item_name }}" + item_dest: "{{ remote_path }}/{{ item_name }}" + when: item != "" diff --git a/roles/ands_kaas/tasks/template.yml b/roles/ands_kaas/tasks/template.yml new file mode 100644 index 0000000..6a81dd7 --- /dev/null +++ b/roles/ands_kaas/tasks/template.yml @@ -0,0 +1,17 @@ +- name: Populate template + template: src="{{ item }}" dest="{{ kaas_template_path }}/{{ item | basename | regex_replace('\.j2','') }}" owner=root group=root mode="0644" + register: result + with_first_found: + - paths: + - "{{ role_path }}/templates/" + - "{{ kaas_project_path }}/templates/" + files: + - "{{ tmpl_name }}" + +- name: Configure KaaS resources + include_role: name="openshift_resource" + vars: + template: "{{ tmpl_name | basename | regex_replace('\\.j2','') }}" + template_path: "{{ kaas_template_path }}" + project: "{{ kaas_project }}" + recreate: "{{ result | changed | ternary (true, false) }}" diff --git a/roles/ands_kaas/tasks/templates.yml b/roles/ands_kaas/tasks/templates.yml new file mode 100644 index 0000000..75d43f3 --- /dev/null +++ b/roles/ands_kaas/tasks/templates.yml @@ -0,0 +1,20 @@ +--- +# Sorting is not enforeced +- name: "Find KaaS templates" + command: "echo {{ item | quote }}" + register: results + changed_when: false + with_fileglob: + - "{{ role_path }}/templates/{{ kaas_template_glob | default('*') }}.j2" + - "{{ kaas_project_path }}/templates/{{ kaas_template_glob | default('*') }}.j2" + +- name: "Sort and execute KaaS templates" + include: "template.yml" + delegate_to: "{{ groups.masters[0] }}" + run_once: true + with_items: "{{ sorted_tmpl }}" + vars: + sorted_tmpl: "{{ results | json_query('results[*].stdout_lines') | sum(start=[]) | map('basename') | sort | unique }}" + loop_control: + loop_var: tmpl_name + diff --git a/roles/ands_kaas/tasks/volume.yml b/roles/ands_kaas/tasks/volume.yml new file mode 100644 index 0000000..b82e55f --- /dev/null +++ b/roles/ands_kaas/tasks/volume.yml @@ -0,0 +1,11 @@ +--- +- name: "Configure {{ name }} fact" + set_fact: "kaas_{{ name }}_path={{ path }}" + +- name: "Ensure {{ path }} exists" + file: + path: "{{ path }}" + state: "directory" + mode: "{{ volume.mode | default(0755) }}" + owner: "{{ volume.owner | default(kaas_project_config.file_owner) | default(kaas_default_file_owner) }}" + group: "{{ volume.group | default(kaas_project_config.file_group) | default(kaas_default_file_group) }}" diff --git a/roles/ands_kaas/templates/0-gfs-volumes.yml.j2 b/roles/ands_kaas/templates/0-gfs-volumes.yml.j2 new file mode 100644 index 0000000..a162c8b --- /dev/null +++ b/roles/ands_kaas/templates/0-gfs-volumes.yml.j2 @@ -0,0 +1,38 @@ +--- +apiVersion: v1 +kind: Template +metadata: + name: + annotations: + descriptions: "KATRIN Volumes" +objects: +{% for name, vol in (kaas_project_config.volumes | default(kaas_openshift_volumes)).iteritems() %} + - apiVersion: v1 + kind: PersistentVolume + metadata: + name: {{ vol.name | default(name) }} + spec: + persistentVolumeReclaimPolicy: Retain + glusterfs: + endpoints: {{ kaas_glusterfs_endpoints }} + path: {{ vol.volume }} + readOnly: {{ not (vol.write | default(false)) }} + accessModes: + - {{ vol.access | default('ReadWriteMany') }} + capacity: + storage: {{ vol.capacity | default(kaas_default_volume_capacity) }} + claimRef: + name: {{ vol.name | default(name) }} + namespace: {{ kaas_project }} + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: {{ vol.name | default(name) }} + spec: + volumeName: {{ vol.name | default(name) }} + accessModes: + - {{ vol.access | default('ReadWriteMany') }} + resources: + requests: + storage: {{ vol.capacity | default(kaas_default_volume_capacity) }} +{% endfor %} diff --git a/roles/ands_kaas/templates/6-kaas-pods.yml.j2 b/roles/ands_kaas/templates/6-kaas-pods.yml.j2 new file mode 100644 index 0000000..9849bd3 --- /dev/null +++ b/roles/ands_kaas/templates/6-kaas-pods.yml.j2 @@ -0,0 +1,173 @@ +#jinja2: trim_blocks: "true", lstrip_blocks: "false" +--- +apiVersion: v1 +kind: Template +metadata: + name: {{ kaas_project }}-pods + annotations: + descriptions: {{ kaas_project_config.description | default(kaas_project ~ "auto-generated pod template") }} +objects: +{% for name, pod in (kaas_project_config.pods | default(kaas_openshift_volumes)).iteritems() %} + {% set pubkey = "kaas_" ~ name ~ "_pubkey" %} + {% set privkey = "kaas_" ~ name ~ "_privkey" %} + {% set cakey = "kaas_" ~ name ~ "_ca" %} + {% if pod.service is defined %} + - apiVersion: v1 + kind: Service + metadata: + name: {{ pod.name | default(name) }} + spec: + selector: + name: {{ pod.name | default(name) }} + {% if pod.service.ports is defined %} + ports: + {% for port in pod.service.ports %} + {% set portmap = (port | string).split('/') %} + - name: "{{ portmap[0] }}" + port: {{ portmap[0] }} + targetPort: {{ (portmap[1] is defined) | ternary(portmap[1], portmap[0]) }} + {% endfor %} + {% endif %} + {% if (pod.service.ports is defined) and (pod.service.host is defined) %} + {% set first_port = (pod.service.ports[0] | string).split('/')[0] %} + - apiVersion: v1 + kind: Route + metadata: + name: kaas + spec: + host: {{ pod.service.host }} + to: + kind: Service + name: {{ pod.name | default(name) }} + port: + targetPort: {{ first_port }} + {% if (first_port == "80") %} + tls: + termination: edge + insecureEdgeTerminationPolicy: Allow + {% if hostvars[inventory_hostname][pubkey] is defined %} + certificate: |- + {{ hostvars[inventory_hostname][pubkey] | indent(10) }} + {% endif %} + {% if hostvars[inventory_hostname][privkey] is defined %} + key: |- + {{ hostvars[inventory_hostname][privkey] | indent(10) }} + {% endif %} + {% if hostvars[inventory_hostname][cakey] is defined %} + caCertificate: |- + {{ hostvars[inventory_hostname][cakey] | indent(10) }} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + - apiVersion: v1 + kind: DeploymentConfig + metadata: + name: kaas + spec: + replicas: {{ pod.sched.replicas | default(1) }} + selector: + name: {{ pod.name | default(name) }} + template: + metadata: + name: {{ pod.name | default(name) }} + labels: + name: {{ pod.name | default(name) }} + strategy: + type: {{ pod.sched.strategy | default('Rolling') }} + triggers: + - type: ConfigChange + spec: + {% if pod.selector is defined %} + nodeSelector: + {% for skey, sval in pod.selector.iteritems() %} + {{ skey }}: "{{ sval }}" + {% endfor %} + {% endif %} + {% set mappings = (pod.images | json_query('[*].mappings') | length) %} + {% if mappings > 0 %} + volumes: + {% for img in pod.images %} + {% set imgidx = loop.index %} + {% for vol in img.mappings %} + - name: vol-{{imgidx}}-{{loop.index}} + persistentVolumeClaim: + claimName: {{ vol.name }} + {% endfor %} + {% endfor %} + {% endif %} + containers: + {% for img in pod.images %} + {% set imgidx = loop.index %} + - name: {{ img.name | default(pod.name) | default(name) }} + image: {{ img.image }} + imagePullPolicy: Always + ports: + {% if img.ports is defined %} + {% for port in img.ports %} + - containerPort: {{ port }} + {% endfor %} + {% else %} + {% for port in pod.service.ports %} + {% set portmap = (port | string).split('/') %} + - containerPort: {{ (portmap[1] is defined) | ternary(portmap[1], portmap[0]) }} + {% endfor %} + {% endif %} + {% if img.env is defined %} + env: + {% for env_name, env_val in img.env.iteritems() %} + {% set env_parts = (env_val | string).split('@') %} + {% if env_parts[0] == "secret" %} + - name: {{ env_name }} + {% set env_sec = (env_parts[1] | string).split('/') %} + valueFrom: + secretKeyRef: + name: {{ env_sec[0] }} + key: {{ env_sec[1] }} + {% elif env_parts[0] == "cm" %} + {% set env_cm = (env_parts[1] | string).split('/') %} + valueFrom: + configMapKeyRef: + name: {{ env_cm[0] }} + key: {{ env_cm[1] }} + {% else %} + value: {{ env_val }} + {% endif %} + {% endfor %} + {% endif %} + {% if img.mappings is defined %} + volumeMounts: + {% for vol in img.mappings %} + - name: vol-{{imgidx}}-{{loop.index}} + subPath: {{ (((kaas_project_config.volumes | default(kaas_openshift_volumes))[vol.name].path | default("")) ~ "/") | regex_replace('^/','') }}{{ vol.path | default("") }} + mountPath: {{ vol.mount }} + {% endfor %} + {% endif %} + {% if img.probes is defined %} + {% for probe in img.probes %} + {% if (probe.type is undefined) %} + {% set seq = ['livenessProbe', 'readynessProbe'] %} + {% elif (probe.type == "liveness") %} + {% set seq = ['livenessProbe'] %} + {% else %} + {% set seq = ['readynessProbe'] %} + {% endif %} + {% for type in seq %} + {{ type }}: + timeoutSeconds: {{ probe.timeout | default(1) }} + initialDelaySeconds: {{ probe.delay | default(10) }} + {% if (probe.cmd is defined) %} + command: "{{ probe.cmd }}" + {% elif (probe.path is defined) %} + httpGet: + path: {{ probe.path }} + port: {{ probe.port | default(80) }} + {% else %} + tcpSocket: + port: {{ probe.port | default(80) }} + {% endif %} + {% endfor %} + {% endfor %} + {% endif %} + {% endfor %} +{% endfor %} -- cgit v1.2.3