Simplify the log url

Drop some of the hard-coded path expectations.

It turns out we can do everything we were doing in the hardcoded
method using string format operations.

This reduces some of the variables that are available for URL
formatting.  Useful variables are made available to the formatters
in a safe manner (so that users can't access job.auth.secrets...).

Co-Authored-By: James E. Blair <jeblair@redhat.com>
Change-Id: Ide646d918f4b8e54658809feaa3a8f5ccf228ebc
diff --git a/tests/fixtures/config/success-url/git/common-config/zuul.yaml b/tests/fixtures/config/success-url/git/common-config/zuul.yaml
index f2d5251..b3ecf6d 100644
--- a/tests/fixtures/config/success-url/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/success-url/git/common-config/zuul.yaml
@@ -19,7 +19,7 @@
 
 - job:
     name: docs-draft-test
-    success-url: http://docs-draft.example.org/{build.parameters[LOG_PATH]}/publish-docs/
+    success-url: http://docs-draft.example.org/{change.number:.2}/{change.number}/{change.patchset}/{pipeline.name}/{job.name}/{build.uuid:.7}/publish-docs/
 
 - job:
     name: docs-draft-test2
diff --git a/zuul/executor/client.py b/zuul/executor/client.py
index fd92dd9..220f82a 100644
--- a/zuul/executor/client.py
+++ b/zuul/executor/client.py
@@ -16,7 +16,6 @@
 import gear
 import json
 import logging
-import os
 import time
 import threading
 from uuid import uuid4
@@ -266,13 +265,6 @@
             params['ZUUL_REF'] = item.change.ref
             params['ZUUL_COMMIT'] = item.change.newrev
 
-        # The destination_path is a unique path for this build request
-        # and generally where the logs are expected to be placed
-        destination_path = os.path.join(item.change.getBasePath(),
-                                        pipeline.name, job.name, uuid[:7])
-        params['BASE_LOG_PATH'] = item.change.getBasePath()
-        params['LOG_PATH'] = destination_path
-
         # This is what we should be heading toward for parameters:
 
         # required:
diff --git a/zuul/model.py b/zuul/model.py
index 5ed2fbd..afa7522 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -96,6 +96,13 @@
     return re.sub(' ', '-', name)
 
 
+class Attributes(object):
+    """A class to hold attributes for string formatting."""
+
+    def __init__(self, **kw):
+        setattr(self, '__dict__', kw)
+
+
 class Pipeline(object):
     """A configuration that ties triggers, reporters, managers and sources.
 
@@ -1433,12 +1440,20 @@
             if job.failure_url:
                 pattern = job.failure_url
         url = None
+        # Produce safe versions of objects which may be useful in
+        # result formatting, but don't allow users to crawl through
+        # the entire data structure where they might be able to access
+        # secrets, etc.
+        safe_change = self.change.getSafeAttributes()
+        safe_pipeline = Attributes(name=self.pipeline.name)
+        safe_job = Attributes(name=job.name)
+        safe_build = Attributes(uuid=build.uuid)
         if pattern:
             try:
-                url = pattern.format(change=self.change,
-                                     pipeline=self.pipeline,
-                                     job=job,
-                                     build=build)
+                url = pattern.format(change=safe_change,
+                                     pipeline=safe_pipeline,
+                                     job=safe_job,
+                                     build=safe_build)
             except Exception:
                 pass  # FIXME: log this or something?
         if not url:
@@ -1631,6 +1646,12 @@
     def updatesConfig(self):
         return False
 
+    def getSafeAttributes(self):
+        return Attributes(project=self.project,
+                          ref=self.ref,
+                          oldrev=self.oldrev,
+                          newrev=self.newrev)
+
 
 class Change(Ref):
     """A proposed new state for a Project."""
@@ -1694,6 +1715,11 @@
             return True
         return False
 
+    def getSafeAttributes(self):
+        return Attributes(project=self.project,
+                          number=self.number,
+                          patchset=self.patchset)
+
 
 class TriggerEvent(object):
     """Incoming event from an external system."""
diff --git a/zuul/scheduler.py b/zuul/scheduler.py
index 7fb1568..dae9fe7 100644
--- a/zuul/scheduler.py
+++ b/zuul/scheduler.py
@@ -897,6 +897,7 @@
             url_pattern = self.config.get('zuul', 'url_pattern')
         else:
             url_pattern = None
+        # TODOv3(jhesketh): url_pattern should be deterministic by zuul
 
         data = {}