Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-71715

Allow plugins with alternate build log visualizations to handle console links from core and other plugins

      Motivation

      Jenkins core and various plugins link directly to the /console page for builds in a number of situations, for example not only the direct link to the console in the sidebar of runs, but also the status icon in the build history widget in Jenkins core and the "proceed"/"abort" button for input steps in pipeline-input-step.

      A few different plugins have or are working on alternate console views, primarily for Pipelines. Blue Ocean has one, although it is not really a direct replacement for the normal console. Pipeline Graph View plugin is working on a new console view for Pipelines as well. CloudBees is also working on a proprietary log viewer plugin for Pipelines.

      We would like for there to be an API that plugins which provide alternate log visualizations can use to handle links to the console from other plugins. Display URL API plugin offers a mechanism to create "display URLs" for things like external notifications (and for users to choose their personal preferred URL provider), which is useful, but we would like to be able to alter the behavior of existing links in Jenkins, which would require changes to Jenkins core.

      Prototype Implementations

      We have prototyped two main approaches for making this possible. In both approaches we define two new APIs:

      1. In Jenkins core, we add an ExtensionPoint named ConsoleURLProvider (name not final), with a single extensible method with a signature like String ConsoleURLProvider.getUrl(Run).
      2. In display-url-api, we add a new DisplayURLProvider.getConsoleUrl(Run) method, and we implement ConsoleURLProvider with a new @Extension that delegates to the new method.

      Plugins which want to provide an alternate console view would implement DisplayURLProvider and override getConsoleUrl as needed.

      For code in Jenkins core or plugins that wants to link to the console for a build, we have prototyped two possible approaches:

      Approach 1: Modify hard-coded console links in core and plugins to use a new redirect URL

      We would create a new Run.getConsoleDisplayRedirect method (name not final), which uses the ConsoleURLProvider with the highest registered ordinal value to get the console URL, but falls back to /console in case there is no such extension. All existing code that links to the console in Jenkins core and in all plugins would need to change hard-coded references to /console to /consoleDisplayRedirect. Here is an incomplete search of references that might need to be changed.

      This approach seems straightforward and relatively safe in terms of compatibility, but it is not ideal to have to adapt all downstream plugins to use the new URL. If we went down this approach we would look through all plugins in the Jenkins BOM and file PRs to adapt them as part of this change, but we would probably not do so for all plugins, at least not to start with.

      Approach 2: Turn <run>/console itself into a redirect

      We would define a new Run.doConsole method that uses Stapler APIs to redirect the page to ConsoleURLProvider.getUrl for the extension with the highest ordinal value, falling back to serving console.jelly if there is no such extension.

      The benefit of this approach is we don't need to change any existing code in core and plugins that links to <run>/console.

      On the other hand, this approach seems to be potentially a little more dangerous (bugs leading to infinite redirects), a bit slower (because of the redirect), and perhaps logically wrong in some cases where an existing /console link really should go to the classic console view.

      Compatibility and related concerns

      • With either approach, the behavior of the /consoleText and /consoleFull views would be unchanged. The former is accessible via a sidebar link on builds, but the latter is normally only accessed from the UI on the /console view.
        • We think that any programmatic access to the console is most likely to go through /consoleText and so be unaffected by these changes.
      • With the automatic redirect approach, we might need to add a new way to link to the classic console that would bypass the redirect handling (e.g. /consoleFull).
      • TBD, I am sure we are missing some other nuances here

          [JENKINS-71715] Allow plugins with alternate build log visualizations to handle console links from core and other plugins

          Julien Greffe added a comment - - edited PRs: https://github.com/jenkinsci/jenkins/pull/8321 https://github.com/jenkinsci/pipeline-input-step-plugin/pull/145 https://github.com/jenkinsci/workflow-job-plugin/pull/373 https://github.com/jenkinsci/pipeline-graph-view-plugin/pull/289

          Devin Nusbaum added a comment - - edited

          jgreffe Right now, DisplayUrlProvider only takes effect if a redirect URL is looked up in the context of a user who has modified their personal preference, right? (Ignoring the ability to specify a default provider via system property.) I wonder if there are cases for existing /console links where the link is produced in the context of the SYSTEM user, which would not work well today. If so, what we have discussed as a future followup with making it possible for admins easily to easily specify a default DisplayUrlProvider for a controller without using a system property may help in that case, depending on the desired behavior.

          Devin Nusbaum added a comment - - edited jgreffe Right now, DisplayUrlProvider only takes effect if a redirect URL is looked up in the context of a user who has modified their personal preference, right? (Ignoring the ability to specify a default provider via system property.) I wonder if there are cases for existing /console links where the link is produced in the context of the SYSTEM user, which would not work well today. If so, what we have discussed as a future followup with making it possible for admins easily to easily specify a default DisplayUrlProvider for a controller without using a system property may help in that case, depending on the desired behavior.

          Julien Greffe added a comment -

          dnusbaum 

          If the user has defined "Default" provider, I think the system property will be used.

          This means when the SYSTEM user retrieves the DisplayURLProvider:

          • if system property is defined, the related provider will be used to generate the links
          • links will be <run>/display/redirect?page=?

          https://github.com/jenkinsci/display-url-api-plugin/blob/6873b50963bb6e3c66e79dc2934675b83b4ed5ca/src/main/java/org/jenkinsci/plugins/displayurlapi/DisplayURLProvider.java#L192

          Julien Greffe added a comment - dnusbaum   If the user has defined "Default" provider, I think the system property will be used. This means when the SYSTEM user retrieves the DisplayURLProvider: if system property is defined, the related provider will be used to generate the links links will be <run>/display/redirect?page=? https://github.com/jenkinsci/display-url-api-plugin/blob/6873b50963bb6e3c66e79dc2934675b83b4ed5ca/src/main/java/org/jenkinsci/plugins/displayurlapi/DisplayURLProvider.java#L192

          Devin Nusbaum added a comment - - edited

          Based on review feedback, we have reconsidered the API design. display-url-provider is no longer related to this PR directly. Instead, visualization plugins will implement the new ConsoleUrlProvider API on their own. We will still add a DisplayUrlProvider.getConsoleUrl method, but that will be a separate thing purely for external links, which is how display-url-api is designed to be used. I will file a separate ticket for that and link it here.

          Devin Nusbaum added a comment - - edited Based on review feedback, we have reconsidered the API design. display-url-provider is no longer related to this PR directly. Instead, visualization plugins will implement the new ConsoleUrlProvider API on their own. We will still add a DisplayUrlProvider.getConsoleUrl method, but that will be a separate thing purely for external links, which is how display-url-api is designed to be used. I will file a separate ticket for that and link it here.

          Jesse Glick added a comment -

          The core PR was merged; should this now be closed?

          Jesse Glick added a comment - The core PR was merged; should this now be closed?

          Devin Nusbaum added a comment -

          Released in Jenkins 2.433.

          We will still add a DisplayUrlProvider.getConsoleUrl method, but that will be a separate thing purely for external links, which is how display-url-api is designed to be used. I will file a separate ticket for that and link it here.

          We decided against this for now, because we did not find any existing plugins that produce external links directly to the console and so would consume such an API.

          Devin Nusbaum added a comment - Released in Jenkins 2.433 . We will still add a DisplayUrlProvider.getConsoleUrl method, but that will be a separate thing purely for external links, which is how display-url-api is designed to be used. I will file a separate ticket for that and link it here. We decided against this for now, because we did not find any existing plugins that produce external links directly to the console and so would consume such an API.

          Stuart Rowe added a comment -

          It would be useful for external links in email or slack notifications to redirect to the system / user selected console provider. Similar to the display url provider redirect:

          For example:
          https://jenkins-controller.com/job/Test/1/console/redirect

          would redirect the user to either:
          https://jenkins-controller.com/job/Test/1/console/
          https://jenkins-controller.com/job/Test/1/pipeline-console

          Stuart Rowe added a comment - It would be useful for external links in email or slack notifications to redirect to the system / user selected console provider. Similar to the display url provider redirect: For example: https://jenkins-controller.com/job/Test/1/console/redirect would redirect the user to either: https://jenkins-controller.com/job/Test/1/console/ https://jenkins-controller.com/job/Test/1/pipeline-console

          Devin Nusbaum added a comment -

          stuartrowe Yes, see my above comment. ConsoleUrlProvider is explicitly not intended for this purpose though because it requires implementations to return relative URLs (to prevent Jenkins UI navigation from breaking when the Jenkins URL is misconfigured). I think we would need a new API method in DisplayURLProvider in display-url-api, implementations of that API can implement the new method, and consumers of the API that want to create links to the console can consume the new method. Users would be able to configure their preferred display URL provider as before. That said, do you know of any existing plugins which create external links directly to the console though? I did not see any when I looked previously.

          There may be a simpler option for your use case: pipeline-graph-view has an implementation of DisplayURLProvider which uses the graph for getRunURL. Perhaps it would make sense for that plugin to offer two implementations of DisplayURLProvider, one that is graph-biased and one that is console-biased. I work on a proprietary plugin with a single page that shows the Pipeline structure, logs, and other information, and we override getRunURL to return our page, which in practice seems to work well enough (https://docs.cloudbees.com/docs/cloudbees-ci/latest/pipelines/cloudbees-pipeline-explorer-plugin#_cloudbees_pipeline_map if you are interested).

          Devin Nusbaum added a comment - stuartrowe Yes, see my above comment. ConsoleUrlProvider is explicitly not intended for this purpose though because it requires implementations to return relative URLs (to prevent Jenkins UI navigation from breaking when the Jenkins URL is misconfigured). I think we would need a new API method in DisplayURLProvider in display-url-api , implementations of that API can implement the new method, and consumers of the API that want to create links to the console can consume the new method. Users would be able to configure their preferred display URL provider as before. That said, do you know of any existing plugins which create external links directly to the console though? I did not see any when I looked previously. There may be a simpler option for your use case: pipeline-graph-view has an implementation of DisplayURLProvider which uses the graph for getRunURL . Perhaps it would make sense for that plugin to offer two implementations of DisplayURLProvider , one that is graph-biased and one that is console-biased. I work on a proprietary plugin with a single page that shows the Pipeline structure, logs, and other information, and we override getRunURL to return our page, which in practice seems to work well enough ( https://docs.cloudbees.com/docs/cloudbees-ci/latest/pipelines/cloudbees-pipeline-explorer-plugin#_cloudbees_pipeline_map if you are interested).

          Stuart Rowe added a comment -

          dnusbaum I appreciate the response! I don't know of any plugins, but our internal notifications do include console output links as I mentioned.

          Adding a new console specific endpoint to the display-url-api plugin makes sense to me. In that case would you recommend deferring to the ConsoleUrlProvider to determine the redirect URL so there's no need for additional settings?

          Stuart Rowe added a comment - dnusbaum I appreciate the response! I don't know of any plugins, but our internal notifications do include console output links as I mentioned. Adding a new console specific endpoint to the display-url-api plugin makes sense to me. In that case would you recommend deferring to the ConsoleUrlProvider to determine the redirect URL so there's no need for additional settings?

          Devin Nusbaum added a comment -

          In that case would you recommend deferring to the ConsoleUrlProvider to determine the redirect URL so there's no need for additional settings

          Either way, I don't think there would be any new settings. Having the default implementation of a new DisplayURLProvider.getConsoleURL method delegate to ConsoleUrlProvider would only prevent existing DisplayURLProvider implementations from needing to implement the new method assuming that the plugin already implements ConsoleUrlProvider and that the user sets up their console and display URL preferences to match. It seems weird to have only the getConsoleURL method be dynamic like that, but I guess it would probably be fine in practice. Compare the default implementation for artifact links, which were also added after the plugin was originally created: https://github.com/jenkinsci/display-url-api-plugin/blob/f6fddd8a8be956a3acb487d3fede53956efacf62/src/main/java/org/jenkinsci/plugins/displayurlapi/DisplayURLProvider.java#L97-L100 (which I think is not implemented right, it should not use the overridable getRunURL method but instead delegate to a known subclass like ClassicDisplayURLProvider.getRunURL, otherwise plugins that forget to override getArtifactsURL but do override getRunURL can potentially emit broken artifact links).

          For what it's worth, I think the changes would look something like this:

          • Add DisplayURLProvider.getConsoleURL, implementing it either with getRoot + ConsoleUrlProvider or ClassicDisplayURLProvider.getRunURL + console
          • Implement ClassicDisplayURLProvider.getRunURL as ClassicDisplayURLProvider.getRunURL + console
          • Add DisplayURLProviderImpl.getConsoleURL, having it emit redirect links with ?page=console
          • Update RunDisplayAction.getRedirectURL to handle "console" in the switch
          • Update EnvironmentContributorImpl to add an environment variable for the console URL

          Devin Nusbaum added a comment - In that case would you recommend deferring to the ConsoleUrlProvider to determine the redirect URL so there's no need for additional settings Either way, I don't think there would be any new settings. Having the default implementation of a new DisplayURLProvider.getConsoleURL method delegate to ConsoleUrlProvider would only prevent existing DisplayURLProvider implementations from needing to implement the new method assuming that the plugin already implements ConsoleUrlProvider and that the user sets up their console and display URL preferences to match. It seems weird to have only the getConsoleURL method be dynamic like that, but I guess it would probably be fine in practice. Compare the default implementation for artifact links, which were also added after the plugin was originally created: https://github.com/jenkinsci/display-url-api-plugin/blob/f6fddd8a8be956a3acb487d3fede53956efacf62/src/main/java/org/jenkinsci/plugins/displayurlapi/DisplayURLProvider.java#L97-L100 (which I think is not implemented right, it should not use the overridable getRunURL method but instead delegate to a known subclass like ClassicDisplayURLProvider.getRunURL , otherwise plugins that forget to override getArtifactsURL but do override getRunURL can potentially emit broken artifact links). For what it's worth, I think the changes would look something like this: Add DisplayURLProvider.getConsoleURL , implementing it either with getRoot + ConsoleUrlProvider or ClassicDisplayURLProvider.getRunURL + console Implement ClassicDisplayURLProvider.getRunURL as ClassicDisplayURLProvider.getRunURL + console Add DisplayURLProviderImpl.getConsoleURL , having it emit redirect links with ?page=console Update RunDisplayAction.getRedirectURL to handle "console" in the switch Update EnvironmentContributorImpl to add an environment variable for the console URL

            jgreffe Julien Greffe
            jgreffe Julien Greffe
            Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: