How to create a nested view from a list of subviews?

1,376 views
Skip to first unread message

Yoann Lopez

unread,
Sep 19, 2014, 7:58:27 AM9/19/14
to job-dsl...@googlegroups.com


Hi,

I am using job-dsl 1.25. I want to create a nested view containing subviews created in a "each" loop. 

The following snippet works well, and creates viewA and viewB within myNestedView

view (type: NestedView) {
    name
("myNestedView")
    views
{
        view
(type: ListView) {
            name
("viewA")
       
}
        view
(type: ListView) {
            name
("viewB")
       
}
   
}
}



The following snippet creates viewA and viewB outside the nested view.
def myviews = ["viewA", "viewB"]
view
(type: NestedView) {
    name
("myNestedView")
    views
{
        myviews
.each () { v ->
            view
(type: ListView) {
                name
("${v}")
           
}
       
}
   
}
}

Is there a way to create a nested view by iterating on a list for the subviews?

btw, great plugin.

Thank you
Yoann.

Daniel Spilker

unread,
Sep 19, 2014, 9:29:52 AM9/19/14
to job-dsl...@googlegroups.com
Hi,

hm, I'm not sure why that happens, but if you use a plain for loop, everything is fine:

def myviews = ["viewA", "viewB"]
view (type: NestedView) {
    name ("myNestedView")
    views {
      for (def v : myviews) {
            view (type: ListView) {
                name(v)
            }
        }
    }
}

Daniel

--
You received this message because you are subscribed to the Google Groups "job-dsl-plugin" group.
To unsubscribe from this group and stop receiving emails from it, send an email to job-dsl-plugi...@googlegroups.com.
To post to this group, send email to job-dsl...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/job-dsl-plugin/4e874a00-5ae5-49e9-9abd-e43fe9a03e3f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Yoann Lopez

unread,
Sep 19, 2014, 9:50:00 AM9/19/14
to job-dsl...@googlegroups.com
It worked. Thanks a lot.

Yoann.

Matt Sheehan

unread,
Sep 19, 2014, 11:13:55 AM9/19/14
to job-dsl...@googlegroups.com
I think it's because the default resolve strategy for closures is OWNER_FIRST and the owner is the JobParent. So it calls JobParent.view rather than NestedViewsContext.view. One way to get it to work in the closure would be to explicitly call it on the delegate like:

def myviews = ["viewA", "viewB"]
view (type: NestedView) {
    name ("myNestedView")
    views {
        myviews.each { v ->
            delegate.view (type: ListView) {
                name v
            }
        }
    }
}

Eddie Sholl

unread,
Nov 2, 2014, 10:06:39 PM11/2/14
to job-dsl...@googlegroups.com
I was able to solve a similar problem by creating the nested view first, then calling views{} multiple times and creating the view inside each invocation. This was insipired by the topic How do I add a Step in a particular Order using the configure block?  at https://github.com/jenkinsci/job-dsl-plugin/wiki/Frequently-Asked-Questions.

In my case I have a function that has a branch name passed into it, and inside here, multiple jobs are created per branch. I'm now first creating the NestedView, and then passing the view into my job creation function. I'm also creating a view per branch, so I use syntax like:

branchesView.with {
    views {
        view {
           ...
        }
    }
}

The views statement will append every time it is invoked.

Misty Stanley-Jones

unread,
Aug 8, 2016, 7:42:55 PM8/8/16
to job-dsl-plugin, yoann...@gmail.com
I'm bumping this because I am seeing this behavior too, with a much newer DSL. Here's the type of view structure I intend to create:

/* Intended structure:
docs
  All
  Builds
    All
    d4p
    suitehelp
    pdf2
    qa
    cdh
    cloudera
    ...
    spark
  In Progress
  Failed
  Generated
  Maintenance
*/

However, when I try to create it, the doubly-nested listViews created using the 'projects' and 'jobTypes' lists are created at the top level, and not as doubly-nested views inside docs / Builds, as I expect. The structure I get instead is like this:

/* Actual structure:
docs
  All
  Builds
    All
  In Progress
  Failed
  Generated
  Maintenance
d4p
suitehelp
pdf2
qa
cdh
cloudera
...
spark
*/

Here is my code as it stands now. Do you think I should be using a for loop instead of the .each lambda? And can anyone explain why this might b e?

// 'docs' view has all jobs that start with docs-
nestedView("docs") {
  println "Creating or updating nested views for docs"
  description('''All documentation-related Jenkins jobs.<br />
Several views are provided. See the Views menu below.
and <a href="http://unittest.jenkins.cloudera.com/view/docs/view/Failed/">Failed</a> are especially interesting.''')
  filterBuildQueue()
  filterExecutors()
  views {
    println "Creating All view"
    listView('All') {
      jobs {
        regex("docs-.*")
      }
      recurse()
    }
    // Builds have a format like docs-cloudera-master-d4p or docs-kudu-0.9.1-suitehelp
    println "Creating Builds view"
    nestedView('Builds') {
      description('''All doc jobs that create D4P, Suitehelp, PDF, or QA artifacts.<br />
      views {
        println "Creating Builds / All view"
        listView('All') {
          description('''All doc jobs that create D4P, Suitehelp, PDF, or QA artifacts.<br />
          jobs {
            regex('docs-.*-[d4p|suitehelp|pdf2|qa]$')
          }
          statusFilter(StatusFilter.ALL)
        }
        // Easy way to have one view for each rough type of jobs
        def jobTypes = ["d4p", "suitehelp", "pdf2", "qa"]
        jobTypes.each {
          println "Creating Builds / ${it} view."
          listView("${it}") {
            description("""All doc jobs of type ${it}.<br />
            jobs {
              regex("docs-${it}.*")
            }
          }
        } // end jobTypes
        // Easy way to make some project-specific dashboards
        // Matches things like docs-cloudera or docs-connectors
        def projects = ["cdh", "cloudera", "cm", "connectors", "director", "doc_smokes", "hadoop", "hue", "impala", "kafka", "kudu", "legal", "navigator", "rel-notes", "security-bulletins", "sense", "spark"]
        projects.each {
          println "Creating Builds / ${it} view."
          listView("${it}") {
            description("""All doc jobs for project ${it}.<br />
            jobs {
              regex("docs-${it}.*")
            }
          }
        } // end projects
      } // end views inside Builds
    } // end Builds nestedView
    // In Progress
    println "Creating In Progress view."
    listView('In Progress') {
      description("""All doc currently building.<br />
      jobs {
        regex('docs-.*')
      }
      jobFilters {
        buildTrend {
            matchType(MatchType.INCLUDE_MATCHED)
            status(BuildStatusType.STARTED)
        }
      }
      recurse()
    } // end In Progress view
    // Failed
    println "Creating Failed view."
    listView('Failed') {
      description("""All doc jobs that failed the last build.<br />
      jobs {
        regex('docs-.*')
      }
      jobFilters {
        status {
          matchType(MatchType.INCLUDE_MATCHED)
          status(Status.FAILED)
          status(Status.UNSTABLE)
        }
      }
      recurse()
    } // end Failed view

    // Generated view (for jobs that generate content) matches a regex
    println "Creating Generated view."
    listView('Generated') {
      description('Doc jobs that create content from source or a running CM instance.')
      jobs {
        regex('docs-[Convert|Get].*')
      }
      jobFilters {
        status {
          matchType(MatchType.INCLUDE_MATCHED)
          status(Status.FAILED)
          status(Status.UNSTABLE)
        }
      }
      recurse()
    } // end Generated view

    // Maintenance view only has specific jobs added to it
    println "Creating Maintenance view."
    listView('Maintenance') {
      description('Doc jobs that are run periodically, such as link checkers or Git reports.')
      jobs {
        regex('docs-[linklint|report].*')
      }
      recurse()
    } // end Maintenance view
  } // end views inside Docs
} // end docs nestedView

Daniel Spilker

unread,
Aug 8, 2016, 7:46:31 PM8/8/16
to job-dsl...@googlegroups.com

--
You received this message because you are subscribed to the Google Groups "job-dsl-plugin" group.
To unsubscribe from this group and stop receiving emails from it, send an email to job-dsl-plugin+unsubscribe@googlegroups.com.
To post to this group, send email to job-dsl-plugin@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/job-dsl-plugin/c4d78b6a-154f-456c-864d-c57cc2bc66f6%40googlegroups.com.

Misty Stanley-Jones

unread,
Aug 8, 2016, 7:51:03 PM8/8/16
to job-dsl-plugin
Thanks, Daniel. I did confirm that using syntax like this fixed the problem:

        def jobTypes = ["d4p", "suitehelp", "pdf2", "qa"]
        for (def jt : jobTypes) {
          println "Creating Builds / ${jt} view."
          listView("${jt}") {
            ...

I'll read the FAQ to try to understand why. I'm not a Groovy expert, so hopefully this email thread will help the next person who stumbles upon this.

To unsubscribe from this group and stop receiving emails from it, send an email to job-dsl-plugi...@googlegroups.com.
To post to this group, send email to job-dsl...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages