diff --git a/roles/stage-output/README.rst b/roles/stage-output/README.rst new file mode 100644 index 000000000..c503758e2 --- /dev/null +++ b/roles/stage-output/README.rst @@ -0,0 +1,49 @@ +Stage job output on the remote node + +Takes as input a dictionary of files/folders named 'zuul_copy_output'. +Copies contents into {{ zuul_output_dir }} on the remote node and is +intended to be used before output fetching in a base job's post-playbook. + +**Role Variables** + +.. zuul:rolevar:: zuul_copy_output + :default: None + + Dictionary of files and folders to be staged. + + The input is a dictionary so that it can accumulated via zuul variable + merging. Keys of the dictionary will be things to copy. Valid values + describe the type of output to copy: + + * logs + * artifacts + * docs + * null # ansible null, not the string null + + null overrides the will of a parent job to copy something instructing + not to copy. + +.. zuul:rolevar:: stage_dir + :default: {{ ansible_user_dir }} + + The stage directory on the remote node. + +.. zuul:rolevar:: extensions_to_txt + :default: null + + A list of file extensions to be replaced with .txt when staging. + This can be useful to ensure that text files with an extension not + registered in the web server may be viewed via browser when uploaded + to a file server. + + Note that this is only used for files listed directly in + `zuul_copy_output` and it won't be applied to files contained in + folders listed in `zuul_copy_output`. + + Example: + + extensions_to_txt: + - conf + - log + + zuul.conf --(staged as)--> zuul_conf.txt diff --git a/roles/stage-output/defaults/main.yaml b/roles/stage-output/defaults/main.yaml new file mode 100644 index 000000000..daece5503 --- /dev/null +++ b/roles/stage-output/defaults/main.yaml @@ -0,0 +1,2 @@ +stage_dir: "{{ ansible_user_dir }}" +extensions_to_txt: diff --git a/roles/stage-output/tasks/main.yaml b/roles/stage-output/tasks/main.yaml new file mode 100644 index 000000000..58b0a1248 --- /dev/null +++ b/roles/stage-output/tasks/main.yaml @@ -0,0 +1,47 @@ +- name: Register sources + stat: + path: "{{ item.key }}" + with_dict: "{{ zuul_copy_output }}" + register: sources + +- name: Build the replace regex + set_fact: + extensions_regex: "{{ extensions_to_txt | join('|') | default('__do_not_replace__') }}" + +- debug: + var: extensions_regex + +# TODO(andreaf) We might want to enforce that item.value is a valid value +# in docs, artifacts, logs. Null case already handled. +# We don't check if the item is a file before renaming, but it is not likely +# to have directories with log, yaml or conf extension. +- name: Set source and destination for files and folders + set_fact: + source: "{{ item.stat.path }}" + dest: "{{ item.item.value }}/{{ item.stat.path|basename|regex_replace('\\.(' + extensions_regex + ')$', '_\\1.txt') }}" + with_items: "{{ sources.results }}" + when: + - item.stat.exists + - item.item.value + register: results + +- name: Build a list of source, dest dictionaries for text files + set_fact: + all_sources: "{{ results.results | selectattr('ansible_facts', 'defined') | map(attribute='ansible_facts') | list }}" + +- name: ensure target folders exist + become: true + file: + path: "{{ stage_dir }}/{{ item }}" + state: directory + owner: "{{ ansible_user }}" + with_items: + - docs + - artifacts + - logs + +- name: Copy text files to staging folder + # remote_src copy does not work recursively, synchronise is restricted by + # zuul, using command + command: cp -pR {{ item.source}} {{ stage_dir }}/{{ item.dest }} + with_items: "{{ all_sources }}"