From c1ccef37de3f7fd307139a9d62fa2dc7a404b069 Mon Sep 17 00:00:00 2001 From: Abhyudaya Sharma Date: Tue, 12 Feb 2019 03:58:54 +0530 Subject: [PATCH] [JENKINS-55933] Add configuration to test slowdowns in the plugin (#57) * Add configuration to test slowdowns in the plugin * Cleanup unused files * Remove unnecessary plugins from plugins.txt Dependencies are automatically installed in `install-plugins.sh` from the base jenkins/jenkins image. * Update LICENSE.md * Change Docker Image names in Makefile and README.md --- src/test/performance/Dockerfile | 33 ++++ src/test/performance/LICENSE.md | 21 +++ src/test/performance/Makefile | 8 + src/test/performance/README.md | 34 ++++ src/test/performance/init_scripts/pom.xml | 153 ++++++++++++++++++ .../src/main/groovy/GroovyBootstrap.groovy | 106 ++++++++++++ .../src/main/groovy/demo/README.md | 5 + .../groovy/demo/jenkins-buildPlugin.groovy | 3 + .../plugins/PipelineHelper.groovy | 78 +++++++++ .../src/main/groovy/scripts/Auth.groovy | 26 +++ .../src/main/groovy/scripts/Docker.groovy | 91 +++++++++++ .../main/groovy/scripts/MasterComputer.groovy | 18 +++ .../groovy/scripts/ProductionFolder.groovy | 43 +++++ .../main/groovy/scripts/SystemFolder.groovy | 30 ++++ .../src/main/groovy/scripts/Tools.groovy | 18 +++ .../src/main/groovy/scripts/Views.groovy | 30 ++++ src/test/performance/jenkins.yaml | 61 +++++++ src/test/performance/jenkins2.sh | 26 +++ src/test/performance/plugins.txt | 15 ++ src/test/performance/pom.xml | 40 +++++ 20 files changed, 839 insertions(+) create mode 100644 src/test/performance/Dockerfile create mode 100644 src/test/performance/LICENSE.md create mode 100644 src/test/performance/Makefile create mode 100644 src/test/performance/README.md create mode 100644 src/test/performance/init_scripts/pom.xml create mode 100644 src/test/performance/init_scripts/src/main/groovy/GroovyBootstrap.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/demo/README.md create mode 100644 src/test/performance/init_scripts/src/main/groovy/demo/jenkins-buildPlugin.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/io/jenkins/systemgroovy/plugins/PipelineHelper.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/Auth.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/Docker.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/MasterComputer.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/ProductionFolder.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/SystemFolder.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/Tools.groovy create mode 100644 src/test/performance/init_scripts/src/main/groovy/scripts/Views.groovy create mode 100644 src/test/performance/jenkins.yaml create mode 100644 src/test/performance/jenkins2.sh create mode 100644 src/test/performance/plugins.txt create mode 100644 src/test/performance/pom.xml diff --git a/src/test/performance/Dockerfile b/src/test/performance/Dockerfile new file mode 100644 index 00000000..dbd57633 --- /dev/null +++ b/src/test/performance/Dockerfile @@ -0,0 +1,33 @@ +FROM jenkins/jenkins:2.138.2 +MAINTAINER Oleg Nenashev +LABEL Description="This demo shows how to setup Jenkins Config-as-Code with Docker, Pipeline, and Groovy Hook Scripts" Vendor="Oleg Nenashev" Version="0.2" + +ENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental +COPY plugins.txt /usr/share/jenkins/ref/plugins.txt +RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt + +COPY init_scripts/src/main/groovy/ /usr/share/jenkins/ref/init.groovy.d/ + +# TODO: It should be configurable in "docker run" +ARG DEV_HOST=192.168.101.57 +ARG CREATE_ADMIN=true +# If false, only few runs can be actually executed on the master +# See JobRestrictions settings +ARG ALLOW_RUNS_ON_MASTER=false +ARG LOCAL_PIPELINE_LIBRARY_PATH=/var/jenkins_home/pipeline-library + +ENV CONF_CREATE_ADMIN=$CREATE_ADMIN +ENV CONF_ALLOW_RUNS_ON_MASTER=$ALLOW_RUNS_ON_MASTER + +# Directory for Pipeline Library development sample +ENV LOCAL_PIPELINE_LIBRARY_PATH=${LOCAL_PIPELINE_LIBRARY_PATH} +RUN mkdir -p ${LOCAL_PIPELINE_LIBRARY_PATH} + +VOLUME /var/jenkins_home/pipeline-library +VOLUME /var/jenkins_home/pipeline-libs +EXPOSE 5005 + +COPY jenkins2.sh /usr/local/bin/jenkins2.sh +ENV CASC_JENKINS_CONFIG=/var/jenkins_home/jenkins.yaml +COPY jenkins.yaml /var/jenkins_home/jenkins.yaml +ENTRYPOINT ["tini", "--", "/usr/local/bin/jenkins2.sh"] diff --git a/src/test/performance/LICENSE.md b/src/test/performance/LICENSE.md new file mode 100644 index 00000000..04733fcf --- /dev/null +++ b/src/test/performance/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017-2019 Oleg Nenashev, Abhyudaya Sharma and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/test/performance/Makefile b/src/test/performance/Makefile new file mode 100644 index 00000000..6ba03d30 --- /dev/null +++ b/src/test/performance/Makefile @@ -0,0 +1,8 @@ +build: + docker build -t abhyudaya/jenkins-role-strategy-slowdown-config . + +run: + docker run --rm --name ci-jenkins-io-dev -v maven-repo:/root/.m2 -v ${MY_PIPELINE_LIBRARY_DIR}:/var/jenkins_home/pipeline-library -v ${MY_OTHER_PIPELINE_LIBS_DIRS}:/var/jenkins_home/pipeline-libs -e DEV_HOST=${CURRENT_HOST} -p 8080:8080 -p 50000:50000 abhyudaya/jenkins-role-strategy-slowdown-config + +debug: + docker run --rm --name ci-jenkins-io-dev -e DEBUG=true -p 5005:5005 -v maven-repo:/root/.m2 -v ${MY_PIPELINE_LIBRARY_DIR}:/var/jenkins_home/pipeline-library -v ${MY_OTHER_PIPELINE_LIBS_DIRS}:/var/jenkins_home/pipeline-libs -e DEV_HOST=${CURRENT_HOST} -p 8080:8080 -p 50000:50000 abhyudaya/jenkins-role-strategy-slowdown-config diff --git a/src/test/performance/README.md b/src/test/performance/README.md new file mode 100644 index 00000000..41004d8e --- /dev/null +++ b/src/test/performance/README.md @@ -0,0 +1,34 @@ +Demo image for Testing the Plugin's performance +=== + +This configuration is designed to experience the performance slowdowns on a large number +of roles. Based on [oleg-nenashev/demo-jenkins-config-as-code](https://github.com/oleg-nenashev/demo-jenkins-config-as-code). + +### Usage + +Run image: + +```shell +docker run --rm --name ci-jenkins-io-dev -v maven-repo:/root/.m2 -e DEV_HOST=${CURRENT_HOST} -p 8080:8080 -p 50000:50000 abhyudaya/jenkins-role-strategy-slowdown-config +``` + +Jenkins will need to connect to the Docker host to run agents. +If you use Docker for Mac, use `-Dio.jenkins.dev.host` and additional `socat` image for forwarding. + +```shell +docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 2376:2375 bobrik/socat TCP4-LISTEN:2375,fork,reuseaddr UNIX-CONNECT:/var/run/docker.sock +``` + +##### Debugging Master + +In order to debug the master, use the `-e DEBUG=true -p 5005:5005` when starting the container. +Jenkins will be suspended on the startup in such case. + +If you open parent POM as a Maven project in your IDE, +you will be also able to debug initialization Groovy scripts. + +### Building image + +```shell +docker build -t abhyudaya/jenkins-role-strategy-slowdown-config . +``` diff --git a/src/test/performance/init_scripts/pom.xml b/src/test/performance/init_scripts/pom.xml new file mode 100644 index 00000000..cc4742c4 --- /dev/null +++ b/src/test/performance/init_scripts/pom.xml @@ -0,0 +1,153 @@ + + + 4.0.0 + + org.jenkins-ci.plugins + plugin + 2.28 + + + io.jenkins.systemgroovy.demo + initscripts + Jenkins Config-as-Code Demo Scripts + Initialization scripts for Jenkins Config-as-Code demo + 1.0-SNAPSHOT + + + + Oleg Nenashev + Jenkins project + https://jenkins.io + + + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + repo + + + + + 2.73.3 + 8 + + + + + + + org.jenkins-ci.plugins + matrix-auth + 2.1 + provided + + + org.jenkins-ci.plugins + cloudbees-folder + 5.12 + + + org.jenkins-ci.plugins.workflow + workflow-aggregator + 2.5 + provided + + + org.jenkins-ci.plugins + git + 3.3.2 + provided + + + com.github.kostyasha.yet-another-docker + yet-another-docker-plugin + 0.1.0-rc37 + provided + + + com.synopsys.jenkinsci + ownership + 0.10.0 + provided + + + com.synopsys.arc.jenkinsci.plugins + job-restrictions + 0.6 + provided + + + org.jenkins-ci.plugins + role-strategy + 2.5.1 + provided + + + org.jenkins-ci.plugins + mailer + 1.20 + provided + + + org.jenkins-ci.plugins + authorize-project + 1.3.0 + provided + + + org.jvnet.hudson.plugins + locale + 1.2 + provided + + + hudson.plugins.filesystem_scm + filesystem_scm + 1.21-alpha-1 + provided + + + + + + + org.codehaus.gmaven + gmaven-plugin + 1.5-jenkins-3 + + + org.codehaus.gmaven.runtime + gmaven-runtime-1.8 + 1.5-jenkins-3 + + + + + + compile + testCompile + + + + + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + \ No newline at end of file diff --git a/src/test/performance/init_scripts/src/main/groovy/GroovyBootstrap.groovy b/src/test/performance/init_scripts/src/main/groovy/GroovyBootstrap.groovy new file mode 100644 index 00000000..c8ab85c9 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/GroovyBootstrap.groovy @@ -0,0 +1,106 @@ +/* + * The MIT License + * + * Copyright (c) 2017 Oleg Nenashev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +import org.codehaus.groovy.control.CompilerConfiguration +import static java.util.logging.Level.INFO +import static java.util.logging.Level.WARNING; +import java.util.logging.Logger; +import javax.annotation.Nonnull; +import javax.servlet.ServletContext; +import jenkins.model.Jenkins; + +/** + * Bootstraps the standard Jenkins initialization logic. + * The bootstrap adds support of Groovy classes and propagates execution failures. + * The started scripts will be debuggable in IDE via Remote Debugger inside a running instance. + * + * @author Oleg Nenashev + */ +class GroovyInitBootstrap { + private final Binding bindings = new Binding() + private final ServletContext servletContext + private final File home + private final GroovyClassLoader groovyClassloader + private final CompilerConfiguration compilerConfiguration = CompilerConfiguration.DEFAULT + + private GroovyInitBootstrap(Jenkins j) { + this(j.servletContext, j.rootDir, j.pluginManager.uberClassLoader) + } + + GroovyInitBootstrap(@Nonnull ServletContext servletContext, @Nonnull File home, @Nonnull ClassLoader groovyClassloader) { + this.servletContext = servletContext + this.home = home + compilerConfiguration.classpath = new File(home, "init.groovy.d/").absolutePath + this.groovyClassloader = new GroovyClassLoader(groovyClassloader, compilerConfiguration, true) + } + + GroovyBootstrap bind(String name, Object o) { + bindings.setProperty(name,o) + return this + } + + /** + * Runs the bootstrap and executes all scripts in {@code init.groovy.d/scripts}. + * @throws Error Execution failed, should be considered as fatal. + */ + void run() { + File scriptsDir = new File(home, "init.groovy.d/scripts") + if (scriptsDir.isDirectory()) { + File[] scripts = scriptsDir.listFiles(new FileFilter() { + boolean accept(File f) { + return f.name.endsWith(".groovy") + } + }) + if (scripts!=null) { + // sort to run them in an alphabetic order + scripts.sort().each { + execute(it) + } + } + } + } + + /** + * Executes the specified Groovy file. + * @param f Groovy file + * @throws Error Execution failed, should be considered as fatal. + */ + protected void execute(@Nonnull File f) { + if (f.exists()) { + LOGGER.log(INFO, "Executing {0}", f) + try { + GroovyCodeSource codeSource = new GroovyCodeSource(f) + new GroovyShell(groovyClassloader, bindings).evaluate(codeSource) + } catch (IOException e) { + LOGGER.log(WARNING, "Failed to execute " + f, e); + throw new Error("Failed to execute " + f, e) + } + } + } + + private static final Logger LOGGER = Logger.getLogger(GroovyBootstrap.class.getName()); +} + +GroovyInitBootstrap bootstrap = new GroovyInitBootstrap(Jenkins.instance) +bootstrap.run() diff --git a/src/test/performance/init_scripts/src/main/groovy/demo/README.md b/src/test/performance/init_scripts/src/main/groovy/demo/README.md new file mode 100644 index 00000000..c3e66e25 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/demo/README.md @@ -0,0 +1,5 @@ +Demo jobs +=== + +This directory contains a set of demo `Jenkinsfile`s. +System Groovy scripts process this directory and create jobs for each job. diff --git a/src/test/performance/init_scripts/src/main/groovy/demo/jenkins-buildPlugin.groovy b/src/test/performance/init_scripts/src/main/groovy/demo/jenkins-buildPlugin.groovy new file mode 100644 index 00000000..e8639877 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/demo/jenkins-buildPlugin.groovy @@ -0,0 +1,3 @@ +buildPlugin(platforms: ['linux'], + repo: 'https://github.com/jenkinsci/job-restrictions-plugin.git', + findbugs: [archive: true, unstableTotalAll: '0']) diff --git a/src/test/performance/init_scripts/src/main/groovy/io/jenkins/systemgroovy/plugins/PipelineHelper.groovy b/src/test/performance/init_scripts/src/main/groovy/io/jenkins/systemgroovy/plugins/PipelineHelper.groovy new file mode 100644 index 00000000..baa784d5 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/io/jenkins/systemgroovy/plugins/PipelineHelper.groovy @@ -0,0 +1,78 @@ +package io.jenkins.systemgroovy.plugins + +import com.cloudbees.hudson.plugins.folder.Folder +import hudson.plugins.filesystem_scm.FSSCM +import org.apache.commons.io.FilenameUtils +import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition +import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition +import org.jenkinsci.plugins.workflow.job.WorkflowJob +import org.jenkinsci.plugins.workflow.libs.FolderLibraries +import org.jenkinsci.plugins.workflow.libs.LibraryConfiguration +import org.jenkinsci.plugins.workflow.libs.SCMRetriever + +/** + * Helper script for Pipeline job management. + * @author Oleg Nenashev + * @since TODO + */ +class PipelineHelper { + + static WorkflowJob createDemo(File file, Folder folder, String name = null, boolean useScmSource = true) { + String jobName = name ?: FilenameUtils.removeExtension(file.name) + def descriptionFile = new File(file.path.replace(".groovy", ".txt")) + def descriptionText = descriptionFile.exists() ? descriptionFile.text : null + + if (useScmSource) { + return createScmPipelineJob(jobName, folder, file, descriptionText) + } else { + return createPipelineJob(jobName, folder, file.text, true, descriptionText) + } + } + + static WorkflowJob createPipelineJob(String name, Folder folder, String script, + boolean sandbox = true, String description = null) { + def p = folder.createProject(WorkflowJob.class, name) + if (description != null) { + p.description = description + } + p.definition = new CpsFlowDefinition( + script, + sandbox + ) + return p + } + + static WorkflowJob createScmPipelineJob(String name, Folder folder, File script, String description = null) { + def p = folder.createProject(WorkflowJob.class, name) + if (description != null) { + p.description = description + } + p.definition = new CpsScmFlowDefinition( + new FSSCM(script.parent, false, false, null), + script.name + ) + return p + } + + static WorkflowJob createBuildPluginJob(Folder folder, String repo, String organization = "jenkinsci", String nameSuffix = "", String args = null, String extras = "") { + return createPipelineJob("${repo}${nameSuffix}", folder, + "buildPlugin(platforms: ['linux'], repo: 'https://github.com/${organization}/${repo}.git' ${extras})", + true, "Builds the ${repo} plugin" + ) + } + + static def addLocalLibrary(Folder folder, String library, String name = null) throws IOException { + def libraryPath = new File(library) + if (!libraryPath.exists() || !libraryPath.isDirectory()) { + throw new Error("Library path does not exist or it is not a directory: ${library}") + } + def libraryName = name ?: libraryPath.name + def scm = new FSSCM(libraryPath.absolutePath, false, false, null) + LibraryConfiguration lc = new LibraryConfiguration(libraryName, new SCMRetriever(scm)) + lc.with { + implicit = true + defaultVersion = "master" + } + folder.addProperty(new FolderLibraries([lc])) + } +} diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/Auth.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/Auth.groovy new file mode 100644 index 00000000..581f7c8f --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/Auth.groovy @@ -0,0 +1,26 @@ +import hudson.model.User +import jenkins.model.Jenkins +import jenkins.security.QueueItemAuthenticatorConfiguration +import org.jenkinsci.plugins.authorizeproject.GlobalQueueItemAuthenticator +import org.jenkinsci.plugins.authorizeproject.strategy.TriggeringUsersAuthorizationStrategy + +boolean createAdmin = Boolean.getBoolean("io.jenkins.dev.security.createAdmin") + +println("=== Configuring users") +def securityRealm = Jenkins.instance.getSecurityRealm() +for (int i = 0; i < 300; i++) { + String userName = "user" + i; + User user = securityRealm.createAccount(userName, "user") + user.setFullName(userName.toUpperCase(Locale.US)) +} + +if (createAdmin) { + User admin = securityRealm.createAccount("admin", "admin") + admin.setFullName("Admin") +} + +println("=== Configure Authorize Project") +GlobalQueueItemAuthenticator auth = new GlobalQueueItemAuthenticator( + new TriggeringUsersAuthorizationStrategy() +) +QueueItemAuthenticatorConfiguration.get().authenticators.add(auth) diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/Docker.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/Docker.groovy new file mode 100644 index 00000000..735f5b80 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/Docker.groovy @@ -0,0 +1,91 @@ +import com.github.kostyasha.yad.DockerCloud +import com.github.kostyasha.yad.DockerConnector +import com.github.kostyasha.yad.DockerContainerLifecycle +import com.github.kostyasha.yad.DockerSlaveTemplate +import com.github.kostyasha.yad.commons.DockerCreateContainer +import com.github.kostyasha.yad.commons.DockerImagePullStrategy +import com.github.kostyasha.yad.commons.DockerPullImage +import com.github.kostyasha.yad.commons.DockerRemoveContainer +import com.github.kostyasha.yad.commons.DockerStopContainer +import com.github.kostyasha.yad.launcher.DockerComputerJNLPLauncher +import com.github.kostyasha.yad.strategy.DockerOnceRetentionStrategy +import hudson.tasks.Maven.MavenInstallation +import hudson.tools.ToolLocationNodeProperty +import jenkins.model.Jenkins +import jenkins.model.JenkinsLocationConfiguration +import hudson.model.Node.Mode + +println("=== Setting Jenkins URL") +String host = java.lang.System.getProperty("io.jenkins.dev.host") +if (host == null) { + host = "localhost" +} else { + JenkinsLocationConfiguration.get().setUrl("http://${host}:8080") +} + +println("=== Installing Docker Cloud for Linux nodes") +static DockerSlaveTemplate fromTemplate(String image) { + return new DockerSlaveTemplate( + maxCapacity: 10, + mode: Mode.EXCLUSIVE, + numExecutors: 1, + launcher: new DockerComputerJNLPLauncher( + jenkinsUrl: JenkinsLocationConfiguration.get().url, + launchTimeout: 100, + noCertificateCheck: true + ), + dockerContainerLifecycle: new DockerContainerLifecycle( + image: image, + pullImage: new DockerPullImage( + pullStrategy: DockerImagePullStrategy.PULL_ONCE + ), + createContainer: new DockerCreateContainer( + privileged: false, + tty: false + ), + stopContainer: new DockerStopContainer( + timeout: 100 + ), + removeContainer: new DockerRemoveContainer( + force: true, + removeVolumes: true + ) + ), + retentionStrategy: new DockerOnceRetentionStrategy(30) + ) +} + +// Default agent image +final DockerSlaveTemplate defaultJnlpAgentTemplate = fromTemplate("jenkins/jnlp-slave") +defaultJnlpAgentTemplate.with { + // Default label to "docker", no caching + // User - jenkins (default) +} + +// Custom image for Maven builds +MavenInstallation.DescriptorImpl mavenDescriptor = Jenkins.instance.getDescriptorByType(MavenInstallation.DescriptorImpl.class); +final DockerSlaveTemplate mavenBuilderTemplate = fromTemplate("onenashev/demo-jenkins-maven-builder") +mavenBuilderTemplate.with { + labelString = "docker linux mvnBuilder" + remoteFs = "/root" + ((DockerComputerJNLPLauncher)launcher).user = "root" + //TODO: Make volume names configurable + dockerContainerLifecycle.createContainer.volumes = ["maven-repo:/root/.m2", "jar-cache:/root/.jenkins"] + nodeProperties = [ + new ToolLocationNodeProperty( + // Maven from the parent Maven image, we do not want to run the installer each time + new ToolLocationNodeProperty.ToolLocation(mavenDescriptor,"mvn", "/usr/share/maven") + ) + ] + +} + + +Jenkins.instance.clouds.add( + new DockerCloud( + "docker-cloud", + [ defaultJnlpAgentTemplate, mavenBuilderTemplate ], + 10, + //TODO: YAD Plugin does not work well with this image and Unix sockets. Would be useful to migrate + new DockerConnector("tcp://${host}:2376")) +) diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/MasterComputer.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/MasterComputer.groovy new file mode 100644 index 00000000..816e3533 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/MasterComputer.groovy @@ -0,0 +1,18 @@ +import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription +import com.synopsys.arc.jenkins.plugins.ownership.nodes.NodeOwnerHelper +import com.synopsys.arc.jenkins.plugins.ownership.util.ui.UserSelector +import org.jenkinsci.plugins.workflow.job.WorkflowJob +import jenkins.model.Jenkins +import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.nodes.JobRestrictionProperty +import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.logic.OrJobRestriction +import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.logic.MultipleAndJobRestriction +import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.job.RegexNameRestriction +import com.synopsys.arc.jenkins.plugins.ownership.security.jobrestrictions.OwnersListJobRestriction +import io.jenkins.plugins.jobrestrictions.restrictions.job.JobClassNameRestriction +import io.jenkins.plugins.jobrestrictions.util.ClassSelector + +println("== Configuring Master computer") + +// Admin owns the node +NodeOwnerHelper.setOwnership(Jenkins.instance, new OwnershipDescription(true, "admin")) + diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/ProductionFolder.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/ProductionFolder.groovy new file mode 100644 index 00000000..a43346da --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/ProductionFolder.groovy @@ -0,0 +1,43 @@ +// Initializes the production jobs directory, which runs with deployed scripts and repos + +import com.cloudbees.hudson.plugins.folder.Folder +import com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy +import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription +import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerHelper +import hudson.plugins.git.GitSCM +import jenkins.model.Jenkins +import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition +import org.jenkinsci.plugins.workflow.job.WorkflowJob + +println("=== Initialize the Production folder") +if (Jenkins.instance.getItem("Production") != null) { + println("Production folder has been already initialized, skipping the step") + return +} + +// Create multiple projects +GitSCM source1 = new GitSCM("https://gist.github.com/AbhyudayaSharma/1bccbb2e760ca0706907f451347d5727.git") +for (int i = 0; i < 500; i++) { + def myFolder = Jenkins.getInstance().createProject(Folder.class, "Foooooolder" + i) + WorkflowJob project4 = myFolder.createProject(WorkflowJob.class, "test" + i) + project4.setDefinition(new CpsScmFlowDefinition(source1, "Jenkinsfile")) + JobOwnerHelper.setOwnership(project4, new OwnershipDescription(false, "admin", Arrays.asList("user"))) +} + +RoleBasedAuthorizationStrategy strategy = RoleBasedAuthorizationStrategy.getInstance() +def rand = new Random() +for (int i = 0; i < 500; i++) { + def roleName = "myRole" + i + def userName = "user" + i + if (rand.nextBoolean()) { + strategy.doAddRole(RoleBasedAuthorizationStrategy.PROJECT, roleName, + "hudson.model.Item.Discover,hudson.model.Item.Read,hudson.model.Item.Build", + "true", "F(o+)+lder[" + rand.nextInt(10) + rand.nextInt(10) + "]{1,2}") + } else { + strategy.doAddRole(RoleBasedAuthorizationStrategy.PROJECT, roleName, + "hudson.model.Item.Discover,hudson.model.Item.Build,hudson.model.Item.Cancel", + "true", "(((?=Folder)(?=([a-zA-Z]+)*)(?=Folder)(Folder))+)+[" + + rand.nextInt(10) + rand.nextInt(10) + "]*") + } + strategy.doAssignRole(RoleBasedAuthorizationStrategy.PROJECT, roleName, userName) +} diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/SystemFolder.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/SystemFolder.groovy new file mode 100644 index 00000000..e51e2ba8 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/SystemFolder.groovy @@ -0,0 +1,30 @@ +// Initializes the System folder +// In the default configuration Jenkins admin is eligible to start jobs from this directory on the master +import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription +import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerHelper +import jenkins.model.Jenkins +import com.cloudbees.hudson.plugins.folder.Folder +import jenkins.plugins.git.GitSCMSource +import org.jenkinsci.plugins.ownership.model.folders.FolderOwnershipHelper +import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition +import org.jenkinsci.plugins.workflow.libs.FolderLibraries +import org.jenkinsci.plugins.workflow.libs.LibraryConfiguration +import org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever +import org.jenkinsci.plugins.workflow.job.WorkflowJob + +def folder = Jenkins.instance.createProject(Folder.class, "System") + +// Include https://github.com/jenkins-infra/pipeline-library +def pipelineLibrarySource = new GitSCMSource("pipeline-library", "https://github.com/jenkins-infra/pipeline-library.git", null, null, null, false) +LibraryConfiguration lc = new LibraryConfiguration("pipeline-library", new SCMSourceRetriever(pipelineLibrarySource)) +lc.setImplicit(true) +lc.setDefaultVersion("master") +folder.addProperty(new FolderLibraries([lc])) +folder.setDescription("This directory belongs to the Jenkins administrator. " + + "By default he is eligible to run jobs from this Folder on the Master") +FolderOwnershipHelper.setOwnership(folder, new OwnershipDescription(true, "admin")) + +// Add a sample project +WorkflowJob project = folder.createProject(WorkflowJob.class, "Ownership_Plugin_System_Master") +project.setDefinition(new CpsFlowDefinition("buildPlugin(platforms: ['master'], repo: 'https://github.com/jenkinsci/ownership-plugin.git')", true)) +JobOwnerHelper.setOwnership(project, new OwnershipDescription(true, "admin")) diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/Tools.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/Tools.groovy new file mode 100644 index 00000000..9b80a703 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/Tools.groovy @@ -0,0 +1,18 @@ + +import jenkins.model.Jenkins +import hudson.model.JDK +import hudson.tasks.Maven.MavenInstallation; +import hudson.tasks.Maven +import hudson.tools.InstallSourceProperty + +println("--- Setup tool installations") +// By default we offer no JDK7, Nodes should override +JDK jdk7 = new JDK("jdk7", "/non/existent/JVM") +// Java 8 should be a default Java, because we require it for Jenkins 2.60.1+ +JDK jdk8 = new JDK("jdk8", "") +Jenkins.instance.getDescriptorByType(JDK.DescriptorImpl.class).setInstallations(jdk7, jdk8) + + +InstallSourceProperty p = new InstallSourceProperty([new Maven.MavenInstaller("3.5.0")]) +MavenInstallation mvn = new MavenInstallation("mvn", null, [p]) +Jenkins.instance.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(mvn) diff --git a/src/test/performance/init_scripts/src/main/groovy/scripts/Views.groovy b/src/test/performance/init_scripts/src/main/groovy/scripts/Views.groovy new file mode 100644 index 00000000..58c3e010 --- /dev/null +++ b/src/test/performance/init_scripts/src/main/groovy/scripts/Views.groovy @@ -0,0 +1,30 @@ +// Initializes Views on the instance, including the default one. +import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerColumn +import com.synopsys.arc.jenkins.plugins.ownership.jobs.OwnershipJobFilter +import jenkins.model.Jenkins +import hudson.model.ListView +import hudson.views.ListViewColumn + +// Additional view, which also shows owners +ListView withOwnership = new ListView("With ownership") +List columns = new LinkedList<>(withOwnership.getColumns()) +columns.add(3, new JobOwnerColumn()) +withOwnership.with { + includeRegex = ".*" + columns = columns +} +Jenkins.instance.addView(withOwnership) + +// Default view, which recursively shows jobs owned by the current user +ListView myJobs = new ListView("My jobs") +columns = new LinkedList<>(withOwnership.getColumns()) +columns.add(3, new JobOwnerColumn()) +myJobs.with { + includeRegex = ".*" + recurse = true + columns = columns +} +myJobs.jobFilters.add(new OwnershipJobFilter("@Me", true)) +Jenkins.instance.addView(myJobs) + +Jenkins.instance.setPrimaryView(myJobs) diff --git a/src/test/performance/jenkins.yaml b/src/test/performance/jenkins.yaml new file mode 100644 index 00000000..0b36c07f --- /dev/null +++ b/src/test/performance/jenkins.yaml @@ -0,0 +1,61 @@ +jenkins: + mode: NORMAL + numExecutors: 2 + agentProtocols: + - "JNLP4-connect" + - "Ping" + nodeProperties: + - jobRestrictionProperty: + jobRestriction: + or: + first: + multipleAnd: + restrictions: + - ownersList: + usersList: + - selectedUserId: "admin" + acceptsCoOwners: false + - regexNameRestriction: + checkShortName: false + regexExpression: "^System/.+" + second: + jobClassNameRestriction: + jobClasses: + - selectedClass: "org.jenkinsci.plugins.workflow.job.WorkflowJob" + crumbIssuer: + standard: + excludeClientIPFromCrumb: true + disableRememberMe: false + scmCheckoutRetryCount: 0 + projectNamingStrategy: "standard" + markupFormatter: "plainText" + slaveAgentPort: 50000 + myViewsTabBar: "standard" + viewsTabBar: "standard" + + securityRealm: + local: + allowsSignup: false + enableCaptcha: false + authorizationStrategy: + roleBased: + roles: + global: + - name: "admin" + description: "Jenkins administrators" + permissions: + - "Overall/Administer" + assignments: + - "admin" + - name: "readonly" + description: "Read-only users" + permissions: + - "Overall/Read" + assignments: + - "authenticated" +tool: + git: + installations: + - home: "git" + name: "Default" + diff --git a/src/test/performance/jenkins2.sh b/src/test/performance/jenkins2.sh new file mode 100644 index 00000000..38e50c7b --- /dev/null +++ b/src/test/performance/jenkins2.sh @@ -0,0 +1,26 @@ +#! /bin/bash -e +# Additional wrapper, which adds custom environment options for the run + +extra_java_opts=( \ + '-Djenkins.install.runSetupWizard=false -Djenkins.model.Jenkins.slaveAgentPort=50000' \ + '-Djenkins.model.Jenkins.slaveAgentPortEnforce=true' \ + "-Dio.jenkins.dev.security.createAdmin=${CONF_CREATE_ADMIN}" \ + "-Dio.jenkins.dev.security.allowRunsOnMaster=${CONF_ALLOW_RUNS_ON_MASTER}" \ + '-Dhudson.model.LoadStatistics.clock=1000' \ +) + +if [ -z "$DEV_HOST" ] ; then + echo "WARNING: DEV_HOST is undefined, localhost will be used. Some logic like Docker Cloud may work incorrectly." +else + extra_java_opts+=( "-Dio.jenkins.dev.host=${DEV_HOST}" ) +fi + +if [[ "$DEBUG" ]] ; then + extra_java_opts+=( \ + '-Xdebug' \ + '-Xrunjdwp:server=y,transport=dt_socket,address=5005,suspend=y' \ + ) +fi + +export JAVA_OPTS="$JAVA_OPTS ${extra_java_opts[@]}" +exec /usr/local/bin/jenkins.sh "$@" diff --git a/src/test/performance/plugins.txt b/src/test/performance/plugins.txt new file mode 100644 index 00000000..be88b263 --- /dev/null +++ b/src/test/performance/plugins.txt @@ -0,0 +1,15 @@ +cloudbees-folder:6.6 +workflow-aggregator:2.6 +workflow-cps:2.59 +git:3.9.1 +yet-another-docker-plugin:0.1.0-rc48 +ownership:0.12.1 +job-restrictions:0.8 +role-strategy:2.9.0 +authorize-project:1.3.0 +security-inspector:0.5 +monitoring:1.74.0 +filesystem_scm:2.1 +configuration-as-code:1.1 +configuration-as-code-support:1.1 +jdk-tool:1.1 diff --git a/src/test/performance/pom.xml b/src/test/performance/pom.xml new file mode 100644 index 00000000..4c3ff3ca --- /dev/null +++ b/src/test/performance/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + io.jenkins.systemgroovy.demo + parent + role-strategy-plugin-slowdown-config + Configuration to view slowdown in the plugin + 1.0-SNAPSHOT + + + + Oleg Nenashev + Jenkins project + https://jenkins.io + + + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + repo + + + + + init_scripts + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + +