From 6beaaed5879dad0a918175f880db4ac8d25daa3c Mon Sep 17 00:00:00 2001 From: Tristan Cacqueray Date: Sun, 27 May 2018 06:20:15 +0000 Subject: [PATCH] Add base openshift job This change adds base job to use openshift as a build resource. Depends-On: https://review.openstack.org/570668 Change-Id: I74f8fc56b72e40d6b69ed55adc2b44d050f50d3c --- README.rst | 85 ++++++++++++ playbooks/openshift/build-project.yaml | 83 +++++++++++ playbooks/openshift/deploy-project.yaml | 64 +++++++++ playbooks/openshift/pre.yaml | 6 + playbooks/openshift/prepare-namespace.yaml | 131 ++++++++++++++++++ playbooks/openshift/unprivileged-machine.yaml | 9 ++ zuul.yaml | 33 +++++ 7 files changed, 411 insertions(+) create mode 100644 playbooks/openshift/build-project.yaml create mode 100644 playbooks/openshift/deploy-project.yaml create mode 100644 playbooks/openshift/pre.yaml create mode 100644 playbooks/openshift/prepare-namespace.yaml create mode 100644 playbooks/openshift/unprivileged-machine.yaml diff --git a/README.rst b/README.rst index 5d16688..cdc20a0 100644 --- a/README.rst +++ b/README.rst @@ -4,3 +4,88 @@ Zuul Base Jobs This repo contains a generic Zuul base job recommended for use by simple Zuul deployments, and a copy named base-test for use in testing changes to the same. + +Container build resources +------------------------- + +Asuuming this nodepool configuration: + +.. code-block:: yaml + + labels: + - name: openshift-project + - name: openshift-pod + + providers: + - name: openshift-rdocloud + driver: openshift + context: "myproject/openshift.rdocloud:8443/developer" + pools: + - name: main + labels: + - name: openshift-project + type: project + - name: openshift-pod + type: pod + image: docker.io/fedora:28 + + +To use a container as an unprivileged instance, adds in a project: + +.. code-block:: yaml + + # .zuul.yaml + - job: + name: demo-project-linters + parent: base-openshift-container-as-unprivileged-machine + run: playbooks/container-machine.yaml + + - project: + check: + jobs: + - demo-project-linters + + # playbooks/container-machine.yaml + - hosts: pod + tasks: + - command: python3 demo.py + args: + chdir: "{{ zuul.project.src_dir }}" + + +To use a container native job, adds in a project: + +.. code-block:: yaml + + # .zuul.yaml + - job: + name: demo-project-test + parent: base-openshift-container-native + run: playbooks/container-native.yaml + vars: + base_image: "python:3.6" + + - project: + check: + jobs: + - openshift-test + + # playbooks/container-native.yaml + - hosts: localhost + tasks: + - name: Fetch pods list from pre run + include_vars: + file: "{{ zuul.executor.work_root }}/pods.yaml" + + - add_host: + name: "{{ item.pod }}" + group: "{{ item.name }}" + ansible_connection: kubectl + with_items: "{{ pods }}" + + - hosts: demo-project + tasks: + - command: python demo.py + register: demo_output + - fail: + when: "'Hello OpenShift' not in demo_output.stdout" diff --git a/playbooks/openshift/build-project.yaml b/playbooks/openshift/build-project.yaml new file mode 100644 index 0000000..7e36bab --- /dev/null +++ b/playbooks/openshift/build-project.yaml @@ -0,0 +1,83 @@ +--- +- name: prepare dumb bare clone of future state + git: + repo: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}" + dest: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}.git" + bare: yes + tags: + # We don't specify git version to re-use executor state + - skip_ansible_lint + +- name: update server info for dumb http transport + command: git update-server-info + args: + chdir: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}.git" + tags: + # Git module doesn't support update-server-info command + - skip_ansible_lint + +- name: create project dir on http server + command: "oc exec {{ zm_name }} -- mkdir -p {{ zuul.project.src_dir }}.git" + +- name: copy project to http server + command: "oc rsync {{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}.git/ {{ zm_name }}:/opt/app-root/src/{{ zuul.project.src_dir }}.git/" + +- name: create project ImageStream spec + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: ImageStream + metadata: + generation: 1 + labels: + app: "{{ zuul.project.short_name }}" + name: "{{ zuul.project.short_name }}" + spec: + lookupPolicy: + local: false + +- name: create project BuildConfig spec + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: BuildConfig + metadata: + labels: + app: "{{ zuul.project.short_name }}" + name: "{{ zuul.project.short_name }}" + spec: + output: + to: + kind: ImageStreamTag + name: '{{ zuul.project.short_name }}:latest' + postCommit: {} + resources: {} + runPolicy: Serial + source: + git: + ref: master + uri: 'http://staging-http-server:8080/{{ zuul.project.src_dir }}.git' + type: Git + strategy: + sourceStrategy: + from: + kind: ImageStreamTag + name: '{{ base_image }}' + namespace: openshift + type: Source + triggers: + - type: ImageChange + - type: ConfigChange + status: + lastVersion: 1 + +- name: wait for project image built + command: oc get builds -o "jsonpath={.items[?(@.metadata.labels.buildconfig!='staging-http-server')].status.phase}" + register: _project_build + retries: 600 + delay: 1 + until: "'Complete' in _project_build.stdout" diff --git a/playbooks/openshift/deploy-project.yaml b/playbooks/openshift/deploy-project.yaml new file mode 100644 index 0000000..c048286 --- /dev/null +++ b/playbooks/openshift/deploy-project.yaml @@ -0,0 +1,64 @@ +--- +- name: start the project + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: DeploymentConfig + metadata: + generation: 2 + labels: + app: "{{ zuul.project.short_name }}" + name: "{{ zuul.project.short_name }}" + spec: + replicas: 1 + selector: + deploymentconfig: "{{ zuul.project.short_name }}" + strategy: + resources: {} + type: Rolling + template: + metadata: + labels: + app: "{{ zuul.project.short_name }}" + deploymentconfig: "{{ zuul.project.short_name }}" + spec: + containers: + - image: "172.30.1.1:5000/{{ zuul_resources['project'].namespace }}/{{ zuul.project.short_name }}" + name: "{{ zuul.project.short_name }}" + command: [ "/bin/bash", "-c", "--" ] + args: [ "while true; do sleep 30; done;" ] + ports: + - containerPort: 8080 + protocol: TCP + - containerPort: 8443 + protocol: TCP + resources: {} + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + test: false + +- name: get project pod name + command: oc get pods --field-selector=status.phase=Running -o "jsonpath={.items[?(@.metadata.labels.app=='{{ zuul.project.short_name }}')].metadata.name}" + register: _pod_name + retries: 600 + delay: 1 + until: "zuul.project.short_name in _pod_name.stdout" + +# Note: this is a temporary workaround until trusted playbook can inject dynamic inventory for later phase. +# This implementation write the pod name to a work_root/pods.yaml file that is used by the test job. +- name: create pods list + set_fact: + pods_data: + pods: + - name: "{{ zuul.project.short_name }}" + pod: "{{ _pod_name.stdout }}" + +- name: store pods list in work_root + copy: + content: "{{ pods_data | to_yaml }}" + dest: "{{ zuul.executor.work_root }}/pods.yaml" diff --git a/playbooks/openshift/pre.yaml b/playbooks/openshift/pre.yaml new file mode 100644 index 0000000..42eb865 --- /dev/null +++ b/playbooks/openshift/pre.yaml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + tasks: + - include_tasks: prepare-namespace.yaml + - include_tasks: build-project.yaml + - include_tasks: deploy-project.yaml diff --git a/playbooks/openshift/prepare-namespace.yaml b/playbooks/openshift/prepare-namespace.yaml new file mode 100644 index 0000000..ab6d528 --- /dev/null +++ b/playbooks/openshift/prepare-namespace.yaml @@ -0,0 +1,131 @@ +--- +# Note: this can probably be simplified by running a ready to use http server. +# In this PoC, the http server is constructed using the openshift/httpd-ex template +- name: create staging-http ImageStream + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: ImageStream + metadata: + labels: + app: staging-http-server + name: staging-http-server + spec: + lookupPolicy: + local: false + +- name: create staging-http BuildConfig + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: BuildConfig + metadata: + labels: + app: staging-http-server + name: staging-http-server + spec: + output: + to: + kind: ImageStreamTag + name: 'staging-http-server:latest' + postCommit: {} + resources: {} + runPolicy: Serial + source: + git: + ref: master + uri: 'https://github.com/openshift/httpd-ex.git' + type: Git + strategy: + sourceStrategy: + from: + kind: ImageStreamTag + name: 'httpd:2.4' + namespace: openshift + type: Source + triggers: + - type: ImageChange + - type: ConfigChange + status: + lastVersion: 1 + +- name: create staging-http DeploymentConfig + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: DeploymentConfig + metadata: + generation: 2 + labels: + app: staging-http-server + name: staging-http-server + spec: + replicas: 1 + selector: + deploymentconfig: staging-http-server + strategy: + resources: {} + type: Rolling + template: + metadata: + labels: + app: staging-http-server + deploymentconfig: staging-http-server + spec: + containers: + - image: "172.30.1.1:5000/{{ zuul_resources['project'].namespace }}/staging-http-server" + # imagePullPolicy: Always + name: staging-http-server + ports: + - containerPort: 8080 + protocol: TCP + - containerPort: 8443 + protocol: TCP + resources: {} + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + test: false + +- name: create staging-http Service spec + openshift_raw: + state: present + namespace: "{{ zuul_resources['project'].namespace }}" + definition: + apiVersion: v1 + kind: Service + metadata: + labels: + app: staging-http-server + name: staging-http-server + spec: + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: staging-http-server + sessionAffinity: None + type: ClusterIP + status: + loadBalancer: {} + +- name: get staging-http-server pod name + command: oc get pods --field-selector=status.phase=Running -o "jsonpath={.items[?(@.metadata.labels.app=='staging-http-server')].metadata.name}" + register: _zm_name + retries: 600 + delay: 1 + until: "'staging-http' in _zm_name.stdout" + +- name: register staging-http-server pod name + set_fact: + zm_name: "{{ _zm_name.stdout }}" diff --git a/playbooks/openshift/unprivileged-machine.yaml b/playbooks/openshift/unprivileged-machine.yaml new file mode 100644 index 0000000..c1a3c5c --- /dev/null +++ b/playbooks/openshift/unprivileged-machine.yaml @@ -0,0 +1,9 @@ +--- +- hosts: localhost + tasks: + - name: Create src directory + command: "oc exec {{ zuul_resources['pod'].pod }} mkdir src" + + - name: Copy src repos to the pod + command: "oc rsync {{ zuul.executor.src_root }}/ {{ zuul_resources['pod'].pod }}:src/" + no_log: true diff --git a/zuul.yaml b/zuul.yaml index 310c297..9d7d5ba 100644 --- a/zuul.yaml +++ b/zuul.yaml @@ -26,3 +26,36 @@ roles: - zuul: openstack-infra/zuul-jobs timeout: 1800 + +- job: + name: base-openshift-container-native + parent: null + description: | + A base job that build and deploy a container image using the + project future state. + pre-run: playbooks/openshift/pre.yaml + roles: + - zuul: openstack-infra/zuul-jobs + timeout: 1800 + nodeset: + nodes: + - name: project + label: openshift-project + vars: + # Base image to use for BuildConfig + base_image: "python:3.6" + +- job: + name: base-openshift-container-as-unprivileged-machine + parent: null + description: | + A base job to spawn a vanilla container and copy the project + future state + pre-run: playbooks/openshift/unprivileged-machine.yaml + roles: + - zuul: openstack-infra/zuul-jobs + timeout: 1800 + nodeset: + nodes: + - name: pod + label: openshift-pod