<div dir="ltr">+1 on this proposal. <div><br></div><div><div class="gmail_quote"><div dir="ltr">On Tue, Oct 10, 2017 at 11:42 PM Monty Taylor <<a href="mailto:mordred@inaugust.com">mordred@inaugust.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hey everybody!<br>
<br>
I'd like to make a proposal for changing how we do logs/artifacts/docs<br>
collection based on the last few weeks/months of writing things- and of<br>
having to explain to people how to structure build and publish jobs over<br>
the last couple of weeks.<br>
<br>
tl;dr - I'd like to change the publication interface to be directories<br>
on the remote node, not directories on the executor<br>
<br>
Rationale<br>
=========<br>
<br>
If jobs have to copy files back to the executor as part of the<br>
publication interface, then the zuul admins can't change the mechanism<br>
of how artifacts, logs or docs are published without touching a ton of<br>
potentially in-tree job content.<br>
<br>
Doing so should also allow us to stop having a second copy of build<br>
logic in the artifact release jobs.<br></blockquote><div><br></div><div>Having the logic to pull logs in one place allows to have proper isolation </div><div>on the executor between logs coming from different nodes in multi-node</div><div>environments.</div><div><br></div><div>Andrea Frittoli (andreaf)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Implementation<br>
==============<br>
<br>
Define a root 'output' dir on the remote nodes. Different types of<br>
output can be collected by putting them into subdirectories of that dir<br>
on the remote nodes and expecting that base jobs will take care of them.<br>
<br>
People using jobs defined in zuul-jobs should define a variable<br>
"zuul_output_dir", either in site-variables or in their base job. Jobs<br>
in zuul-jobs can and will depend on that variable existing - it will be<br>
considered part of the base job interface zuul-jobs expects.<br>
<br>
Jobs in zuul-jobs will recognize three specific types of job output:<br>
* logs<br>
* artifacts<br>
* docs<br>
<br>
Jobs in zuul-jobs will put job outputs into "{{ zuul_output_dir<br>
}}/logs", "{{ zuul_ouptut_dir }}/artifacts" and "{{ zuul_output_dir<br>
}}/docs" as appropriate.<br>
<br>
A role will be added to zuul-jobs that can be used in base jobs that<br>
will ensure those directories all exist.<br>
<br>
Compression<br>
-----------<br>
<br>
Deployers may choose to have their base job compress items in {{<br>
zuul_output_dir }} as part of processing them, or may prefer not to<br>
depending on whether CPU or network is more precious. Jobs in zuul-jobs<br>
should just move/copy things into {{ zuul_output_dir }} on the node and<br>
leave compression, transfer and publication as a base-job operation.<br>
<br>
Easy Output Copying<br>
-------------------<br>
<br>
A role will also be added to zuul-jobs to facilitate easy/declarative<br>
output copying.<br>
<br>
It will take as input a dictionary of files/folders named<br>
'zuul_copy_output'. The role will copy contents into {{ zuul_output_dir<br>
}} on the remote node and is intended to be used before output fetching<br>
in a base job's post-playook.<br>
<br>
The input will be a dictionary so that zuul variable merging can be used<br>
for accumulating.<br>
<br>
Keys of the dictionary will be things to copy. Valid values will be the<br>
type of output to copy:<br>
<br>
* logs<br>
* artifacts<br>
* docs<br>
* null   # ansible null, not the string null<br>
<br>
null will be used for 'a parent job said to copy this, but this job<br>
wants to not do so'<br>
<br>
The simple content copying role will not be flexible or powerful. People<br>
wanting more expressive output copying have all of the normal tools for<br>
moving files around at their disposal. It will obey the following rules:<br>
<br>
* All files/folders will be copied if they exist, or ignored if they don't<br>
* Items will be copied as-if 'cp -a' had been used.<br>
* Order of files is undefined<br>
* Conflicts between declared files are an error.<br>
<br>
Jobs defined in zuul-jobs should not depend on the {{ zuul_copy_output<br>
}} variable for content they need copied in place on a remote node. Jobs<br>
defined in zuul-jobs should instead copy their output to {{<br>
zuul_output_dir }} This prevents zuul deployers from being required to<br>
put the easy output copying role into their base jobs. Jobs defined in<br>
zuul-jobs may use the role behind the scenes.<br>
<br>
Filter Plugin<br>
-------------<br>
<br>
Since the pattern of using a dictionary in job variables to take<br>
advantage of variable merging is bound to come up more than once, we'll<br>
define a filter plugin in zuul called 'zuul_list_from_value' (or some<br>
better name) that will return the list of keys that match a given value.<br>
So that given the following in a job defintion:<br>
<br>
vars:<br>
   zuul_copy_output:<br>
     foo/bar.html: logs<br>
     other/logs/here.html: logs<br>
     foo/bar.tgz: artifacts<br>
<br>
Corresponding Ansible could do:<br>
<br>
- copy:<br>
     src: {{ item }}<br>
     dest: {{ zuul_log_dir }}<br>
   with_items: {{ zuul_copy_output | zuul_list_from_value(logs) }}<br>
<br>
For OpenStack Today<br>
===================<br>
<br>
We will define zuul_output_dir to be "{{ ansible_user_dir<br>
}}/zuul-output" in our site-variables.yaml file.<br>
<br>
Implement the following in OpenStack's base job:<br>
<br>
We will have the base job will include the simple copying role.<br>
<br>
Logs<br>
----<br>
<br>
Base job post playbook will always grab {{ zuul_output_dir }}/logs from<br>
nodes, same as today:<br>
* If there are more than one node, grab it into {{ zuul.executor.log_dir<br>
}}/{{ inventory_hostname }}.<br>
* If only one node, grab into  {{ zuul.executor.log_dir }} directly<br>
<br>
This will mean moving things like 'fetch-tox-output' logic into the<br>
'tox' role itself, so after it's run the appropriate tox logs will be<br>
copied to {{ zuul_output_dir }}/logs<br>
<br>
Artifacts and docs<br>
------------------<br>
<br>
Base job will always ...<br>
<br>
* Grab {{ zuul_output_dir }}/artifacts and {{ zuul_output_dir }}/docs to<br>
{{ zuul.executor.work_dir }}/artifacts and {{ zuul.executor.work_dir }}/docs<br>
* Publish docs content to <a href="http://logs.openstack.org/%7B%7B" rel="noreferrer" target="_blank">logs.openstack.org/{{</a> zuul_log_path }}/docs -<br>
allows for easy setting of success-url to 'docs/html" in base jobs<br>
regardless of the subdir the job puts docs in to (see docs vs. releasenotes)<br>
* rsync docs content to logs.o.o/{{ zuul_log_path }}/docs after contents<br>
of {{ zuul_output_dir }}/logs so that explicit docs win if there is overlap<br>
* Sign each artifact<br>
* Copy each artifact to {{ zuul.project.short_name }}.{{ zuul.tag }}.{{<br>
suffix }} OR {{ zuul.project.short_name }}.{{ zuul.branch }}.{{ suffix<br>
}} depending on if {{ zuul.tag exists }} or not<br>
* If {{ zuul.change }} is set, upload artifacts to {{ zuul_log_path<br>
}}/artifacts - to allow people to iterate on artifact upload jobs in<br>
check and verify that they work<br>
* If {{ zuul.change }} is not set, upload artifacts to<br>
<a href="http://tarballs.openstack.org/%7B%7B" rel="noreferrer" target="_blank">tarballs.openstack.org/{{</a> zuul.project.short_name }, same as today.<br>
Communicate artifact and docs upload paths to child jobs using:<br>
<a href="https://review.openstack.org/#/c/504808/" rel="noreferrer" target="_blank">https://review.openstack.org/#/c/504808/</a><br>
<br>
Artifact Release jobs<br>
=====================<br>
<br>
The release jobs become similar to v2 release jobs, but can be much more<br>
generalized and reusable. They can also mostly be nodeless jobs<br>
(javascript npm publication is a notable exception - it will need a node)<br>
<br>
Artifacts<br>
---------<br>
<br>
* Fetch artifacts and signatures from <a href="http://tarballs.openstack.org/%7B%7B" rel="noreferrer" target="_blank">tarballs.openstack.org/{{</a><br>
zuul.project.short_name }} - based on values set by parent job<br>
Verify fetched signature is correct<br>
* Upload artifact to appropriate destination(s) (pypi, npm, maven, etc)<br>
<br>
Docs<br>
----<br>
<br>
* Rsync docs from <a href="http://logs.openstack.org/%7B%7B" rel="noreferrer" target="_blank">logs.openstack.org/{{</a> zuul_log_path }}/docs - based on<br>
values set by parent job<br>
* Publish to release-job-specific destination as the current jobs do<br>
<br>
This should allow us to make job/project/content specific publication<br>
jobs without needing those jobs to duplicate content in the build jobs.<br>
<br>
It means we can ALSO put jobs like 'publish-to-pypi' in zuul-jobs<br>
without needing a second copy in openstack-zuul-jobs because openstack<br>
happens to builds tarballs differently. The pypi publication step is the<br>
same no matter how the tarball is produced.<br>
<br>
     - jobs:<br>
         - build-openstack-sphinx-docs<br>
         - publish-sphinx-docs-to-afs:<br>
             dependencies:<br>
                 - build-openstack-sphinx-docs<br>
<br>
Rollout<br>
=======<br>
<br>
The steps should be fairly straightforward (and are fine to do post rollout)<br>
<br>
* Add variable to site-variables<br>
* Add support to base job for creating directories and then copying<br>
content back<br>
* Add easy copy helper role<br>
* Start transitioning jobs in zuul-jobs and openstack-zuul-jobs to using<br>
the new interface - can be done one at a time<br>
* Update usage<br>
<br>
If people are ok with the direction generally, we should be able to get<br>
the enablement pieces in pretty quickly.<br>
<br>
Monty<br>
<br>
_______________________________________________<br>
OpenStack-Infra mailing list<br>
<a href="mailto:OpenStack-Infra@lists.openstack.org" target="_blank">OpenStack-Infra@lists.openstack.org</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-infra</a></blockquote></div></div></div>