From a9fb736f9f439291750afa204aaf57f5e7e45540 Mon Sep 17 00:00:00 2001 From: Trevor Bramwell Date: Sat, 28 Oct 2017 05:55:56 -0700 Subject: [PATCH] Setup and Configure Nexus Adds the Nexus (v2) container and does the following: - Creates the initial 'logs' repository - Configures Jenkins to be able to talk to Nexus by creating a settings.xml, and installing the needed packages on the jenkins-agent. - Installs required plugins for the jjb logs publishing job, including downloading PostBuildScript during the Jenkins container build. - Directs requests to 'jenkins.localhost', etc, on the jenkins-agent through the nginx container. - Sets the Jenkins Markup Formatter to 'Safe HTML' so the logs link can be displayed. Change-Id: I63c783156bcffd1699e9ca7fe1a114ee2ed54bed Signed-off-by: Trevor Bramwell --- .env | 1 + .gitignore | 5 ++ README.rst | 88 +++++++++++++++++----------- config.env | 14 +++++ docker-compose.yml | 22 ++++++- init/config-ci-environment.sh | 31 ++++++++++ jenkins/Dockerfile | 7 +++ jenkins/agent/Dockerfile | 4 +- jenkins/plugins.txt | 6 ++ jenkins/scripts/create-nexus-settings.groovy | 63 ++++++++++++++++++++ jenkins/scripts/global-properties.groovy | 8 ++- 11 files changed, 213 insertions(+), 36 deletions(-) create mode 100644 jenkins/scripts/create-nexus-settings.groovy diff --git a/.env b/.env index 6aca8ce..a469f91 100644 --- a/.env +++ b/.env @@ -3,4 +3,5 @@ ## JENKINS_CONTAINER_VERSION=lts GERRIT_CONTAINER_VERSION=latest +NEXUS_CONTAINER_VERSION=oss OPENLDAP_CONTAINER_VERSION=latest diff --git a/.gitignore b/.gitignore index 878f372..5e12c98 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,8 @@ __pycache__/ docs/_build/ dist/ MANIFEST + +# Cloned repositories +All-Projects +All-Users +ci-management diff --git a/README.rst b/README.rst index bee18c1..c41914c 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,7 @@ The primary services are: * Gerrit * Jenkins - * Nexus [TODO] + * Nexus And the secondary services that support these: @@ -30,8 +30,10 @@ Add the following to /etc/hosts:: 127.0.1.1 jenkins.localhost 127.0.1.2 gerrit.localhost + 127.0.1.3 nexus.localhost -Default user account: sandbox/sandbox +Jenkins/Gerrit login: sandbox/sandbox +Nexus login: admin/admin123 Getting Started --------------- @@ -40,6 +42,7 @@ Add the following to /etc/hosts:: 127.0.1.1 jenkins.localhost 127.0.1.2 gerrit.localhost + 127.0.1.3 nexus.localhost .. Note: This is the same as setting the 'Host' header when sending a GET request to localhost: `curl -H "Host: gerrit.localhost" localhost` @@ -53,6 +56,31 @@ authentication backed by LDAP, a simple ci-management repo in Gerrit, and a basic job in Jenkins that verifies commits to the ci-management repo. +Once the environment is up and running, copy your ssh public-key and add +it to the sandbox user in Gerrit. This can be either be done through the +web interface or from the commandline:: + + ./gerrit-auth.sh ~/.ssh/id_rsa.pub + +Then you can clone the ci-management repo and modify it to your hearts +content:: + + git clone ssh://sandbox@gerrit.localhost:29418/ci-management.git + +Set the gitreview username:: + + git config --add gitreview.username "sandbox" + +And ensure the Change-Id hook exists:: + + git review -s + +Putting up a patchset for review that modifies "\*.yaml" files should +trigger the ci-management-jjb-verify job and add a -1/+1 Verified vote. + +Notes +----- + To bring up a single service in the foreground you can use: .. code-block:: @@ -62,9 +90,8 @@ To bring up a single service in the foreground you can use: Note: dependent services will still be launched but in the background. Hitting '^C' will stop this service, but not the others. -If a service is backed by a Dockerfile (most will be eventually), then -changes to the Dockerfile or files under '$SERVICE/' will require -rebuilding the container: +If a service is backed by a Dockerfile, then changes to the Dockerfile +or files under '$SERVICE/' will require rebuilding the container: .. code-block:: @@ -77,37 +104,21 @@ scratch, run: docker-compose down -v -For other useful docker-compose commands such as logs, see:: - - docker-compose -h - -Next Steps ----------- - -Once the environment is up and running, copy your ssh public-key and add -it to the sandbox user in Gerrit. This can be either be done through the -web interface or from the commandline:: - - ./gerrit-auth.sh ~/.ssh/id_rsa.pub - -Then you can clone the ci-management repo and modify it to your hearts -content:: - - git clone ssh://sandbox@gerrit.localhost:29418/ci-management.git +To run a specific version of one of the services, edit the `.env` file, +and rebuild the containers. For example, to run Jenkins 2.80 set the +value in the `.env` file:: -Set the gitreview username:: + JENKINS_CONTAINER_VERSION=2.80 - git config --add gitreview.username "sandbox" +and run:: -And ensure the Change-Id hook exists:: + docker-compose up -d --build - git review -s +to rebuild the Jenkins image before launching it. -Putting up a patchset for review that modifies "\*.yaml" files should -trigger the ci-management-jjb-verify job and add a -1/+1 Verified vote. +For other useful docker-compose commands such as logs, see:: -Notes ------ + docker-compose -h Init Container ~~~~~~~~~~~~~~ @@ -145,13 +156,15 @@ General: - [ ] Replace 'sandbox' names with 'workshop' since sandbox was just a placeholder - [ ] Setup OpenLDAP over SSL by default -- [ ] Collapse environment config into single file and add lots of - comments, so users don't need to track down the correct file - [ ] Make things more configurable. There are a lot of hardcoded names in Groovy scripts which could be pulled from environment variables +- [x] Collapse environment config into single file and add lots of + comments, so users don't need to track down the correct file Nexus: -- [ ] Setup and configure Nexus +- [ ] Configure Nexus to use LDAP (admin/admin123, or LDAP) +- [x] Setup and configure Nexus + - [x] Create 'logs' Nexus site repo. Gerrit: - [ ] Remove postgres container configuration and replace with MariaDB @@ -163,6 +176,15 @@ Jenkins: instance.hasExplicitPermission(attrs.sid,p) in /configureSecurity/. Reason: java.lang.NullPointerException - [ ] Make Groovy scripts Idempotent +- [x] Set Markup Formatter to HTML Output +- [x] Add LOGS_SERVER, SILO, NEXUS_URL, JENKINS_HOSTNAME +- [x] Create XML config file 'jenkins-log-archives-settings' (depends on credentials) +- [x] Install environment injector plugin + https://wiki.jenkins.io/display/JENKINS/EnvInject+Plugin +- [x] Install plugin for build description + https://plugins.jenkins.io/description-setter +- [x] Manually install postbuildscript.hpi + http://mirrors.jenkins-ci.org/plugins/postbuildscript/0.17/postbuildscript.hpi Init: - [ ] Make steps strongly idempotent (verify the state they modify) diff --git a/config.env b/config.env index 4a55221..7f2bfdf 100644 --- a/config.env +++ b/config.env @@ -1,5 +1,6 @@ ## # Gerrit +# https://hub.docker.com/r/openfrontier/gerrit ## #GERRIT_INIT_ARGS=" \ # --install-plugin=download-commands \ @@ -23,6 +24,7 @@ LDAP_LOCALUSERNAMETOLOWERCASE=true ## # Jenkins +# https://hub.docker.com/r/jenkins/jenkins ## JENKINS_OPTS="" JENKINS_ADMIN_USER=admin @@ -43,6 +45,7 @@ JJB_JENKINS_HOSTNAME=jenkins ## # Postgres +# https://hub.docker.com/r/_/postgres ## POSTGRES_USER=gerrit2 POSTGRES_PASSWORD=gerrit @@ -50,6 +53,7 @@ POSTGRES_DB=reviewdb ## # OpenLDAP +# https://hub.docker.com/r/osixia/openldap ## LDAP_ORGANISATION=Test Org LDAP_DOMAIN=example.org @@ -62,3 +66,13 @@ LDAP_ADMIN_PASSWORD=admin LDAP_TLS=false LDAP_TLS_ENFORCE=false LDAP_REMOVE_CONFIG_AFTER_SETUP=false + +## +# Nexus +# https://hub.docker.com/r/sonatype/nexus/ +## +#CONTEXT_PATH="/nexus" +#MAX_HEAP="768m" +#MIN_HEAP="256m" +#JAVA_OPTS="-server -XX:MaxPermSize192m -Djava.net.preferIPv4Stack=true" +#LAUNCHER_CONF="./conf/jetty.xml ./conf/jetty-requestlog.xml" diff --git a/docker-compose.yml b/docker-compose.yml index 82cc9c1..3285a44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,6 +13,7 @@ services: links: - jenkins - gerrit + - nexus ldap: image: "osixia/openldap:$OPENLDAP_CONTAINER_VERSION" container_name: releng-ldap @@ -43,13 +44,16 @@ services: links: - ldap - nginx - - jenkins-agent jenkins-agent: build: ./jenkins/agent container_name: releng-agent env_file: config.env ports: - "22" + links: + - "nginx:jenkins.localhost" + - "nginx:nexus.localhost" + - "nginx:gerrit.localhost" gerrit: image: "openfrontier/gerrit:$GERRIT_CONTAINER_VERSION" container_name: releng-gerrit @@ -69,6 +73,21 @@ services: links: - ldap - nginx + nexus: + image: "sonatype/nexus:$NEXUS_CONTAINER_VERSION" + container_name: releng-nexus + env_file: config.env + environment: + - VIRTUAL_HOST=nexus.localhost + - VIRTUAL_PORT=8081 + volumes: + - nexus:/sonatype-work + expose: + - "8081" + depends_on: + - nginx + links: + - nginx postgres: image: postgres:latest env_file: config.env @@ -85,4 +104,5 @@ services: volumes: jenkins: gerrit: + nexus: init: diff --git a/init/config-ci-environment.sh b/init/config-ci-environment.sh index 6103c5e..c839529 100644 --- a/init/config-ci-environment.sh +++ b/init/config-ci-environment.sh @@ -178,3 +178,34 @@ if [ ! -f /init/step-8.done ]; then touch /init/step-8.done fi + +## +# Nexus Setup +## +/docker-entrypoint-init.d/wait-for-it.sh nexus:8081 -t 30 + + +# Create Nexus Repos +if [ ! -f /init/step-9.done ]; then + cat > /init/repo.json <<-EOF +{ + "data": { + "name": "logs", + "repoType": "hosted", + "providerRole": "org.sonatype.nexus.proxy.repository.WebSiteRepository", + "exposed": true, + "id": "logs", + "provider": "site", + "writePolicy": "ALLOW_WRITE", + "browseable": true, + "indexable": true, + "notFoundCacheTTL": 1440, + "repoPolicy": "MIXED" + } +} +EOF + curl -H "Content-Type: application/json" -X POST -d @/init/repo.json \ + -u admin:admin123 http://nexus:8081/nexus/service/local/repositories + + touch /init/step-9.done +fi diff --git a/jenkins/Dockerfile b/jenkins/Dockerfile index 48808e1..a7ac5c2 100644 --- a/jenkins/Dockerfile +++ b/jenkins/Dockerfile @@ -18,6 +18,11 @@ RUN echo 2.0 > /usr/share/jenkins/ref/jenkins.install.UpgradeWizard.state COPY plugins.txt /usr/share/jenkins/ref/plugins.txt RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt +# Download PostBuildScript Plugin +RUN curl --fail -sSL \ + http://ftp.osuosl.org/pub/jenkins/plugins/postbuildscript/0.17/postbuildscript.hpi \ + -o /usr/share/jenkins/ref/plugins/postbuildscript.hpi + ENV JENKINS_GROOVY_INIT /usr/share/jenkins/ref/init.groovy.d/ # Configure Basic Security @@ -38,3 +43,5 @@ COPY scripts/create-jenkins-agent.groovy $JENKINS_GROOVY_INIT # Create JJB INI in Config File Plugin COPY scripts/create-jjbini.groovy $JENKINS_GROOVY_INIT +# Create Nexus settings.xml +COPY scripts/create-nexus-settings.groovy $JENKINS_GROOVY_INIT diff --git a/jenkins/agent/Dockerfile b/jenkins/agent/Dockerfile index bb61afc..70177e9 100644 --- a/jenkins/agent/Dockerfile +++ b/jenkins/agent/Dockerfile @@ -3,7 +3,9 @@ FROM jenkinsci/ssh-slave RUN DEBIAN_FRONTEND=noninteractive \ apt-get update \ && apt-get install --no-install-recommends -y python python-pip \ - python-tox \ + python-tox python-dev \ + build-essential zip facter xmlstarlet \ && apt-get clean +RUN /usr/bin/pip install --upgrade setuptools RUN /usr/bin/pip install virtualenv diff --git a/jenkins/plugins.txt b/jenkins/plugins.txt index e741ab6..eb8f8ba 100644 --- a/jenkins/plugins.txt +++ b/jenkins/plugins.txt @@ -1,6 +1,7 @@ ace-editor:1.1 ant:1.5 antisamy-markup-formatter:1.5 +apache-httpcomponents-client-4-api:4.5.3-2.0 authentication-tokens:1.3 bouncycastle-api:2.16.2 branch-api:2.0.11 @@ -9,11 +10,13 @@ cloudbees-folder:6.1.0 config-file-provider:2.16.3 credentials-binding:1.12 credentials:2.1.14 +description-setter:1.9 display-url-api:2.0 docker-commons:1.8 docker-workflow:1.12 durable-task:1.14 email-ext:2.58 +envinject:2.1.5 external-monitor-job:1.7 gerrit-trigger:2.25.0 git-client:2.4.6 @@ -26,8 +29,10 @@ gradle:1.27.1 handlebars:1.1.1 icon-shim:2.0.3 jackson2-api:2.7.3 +javadoc:1.4 jclouds-jenkins:2.14 jquery-detached:1.2.1 +jsch:0.1.54.1 junit:1.20 ldap:1.16 mailer:1.20 @@ -35,6 +40,7 @@ mapdb-api:1.0.9.0 mask-passwords:2.10.1 matrix-auth:1.7 matrix-project:1.11 +maven-plugin:3.0 momentjs:1.1.1 pam-auth:1.3 pipeline-build-step:2.5.1 diff --git a/jenkins/scripts/create-nexus-settings.groovy b/jenkins/scripts/create-nexus-settings.groovy new file mode 100644 index 0000000..4f1f0a4 --- /dev/null +++ b/jenkins/scripts/create-nexus-settings.groovy @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: EPL-1.0 + * + * Copyright (c) 2017 The Linux Foundation and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + */ +import com.cloudbees.plugins.credentials.SystemCredentialsProvider; +import com.cloudbees.plugins.credentials.Credentials; +import com.cloudbees.plugins.credentials.CredentialsScope; +import com.cloudbees.plugins.credentials.domains.Domain; +import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; +import org.jenkinsci.plugins.configfiles.GlobalConfigFiles; +import org.jenkinsci.plugins.configfiles.maven.MavenSettingsConfig; +import org.jenkinsci.plugins.configfiles.maven.MavenSettingsConfig.MavenSettingsConfigProvider; +import org.jenkinsci.plugins.configfiles.maven.security.ServerCredentialMapping; +import jenkins.model.Jenkins; + +def store = SystemCredentialsProvider.getInstance().getStore(); + +Credentials nexus_credentials = + (Credentials) new UsernamePasswordCredentialsImpl( + CredentialsScope.GLOBAL, + "nexus-credentials", + "Nexus Repository Credentials", + "admin", + "admin123"); + +// Create Nexus credentials +store.addCredentials(Domain.global(), nexus_credentials); + + +// Need to wait until after plugins are loaded +Thread.start { + sleep 10000 + println "--> Creating the Nexus Settings file" + + GlobalConfigFiles config_files_store = Jenkins.getInstance() + .getExtensionList(GlobalConfigFiles.class).get(GlobalConfigFiles.class); + + ServerCredentialMapping server_credentials = new ServerCredentialMapping( + "logs", + "nexus-credentials"); + List server_mapping = + new ArrayList(); + server_mapping.add(server_credentials); + + MavenSettingsConfigProvider settings_config = + new MavenSettingsConfigProvider(); + + MavenSettingsConfig config = new MavenSettingsConfig( + "jenkins-log-archives-settings", + "jenkins-logs", + "Nexus Repository", + settings_config.loadTemplateContent(), + MavenSettingsConfig.isReplaceAllDefault, + server_mapping); + config_files_store.save(config); +} diff --git a/jenkins/scripts/global-properties.groovy b/jenkins/scripts/global-properties.groovy index a4fed16..8dadc23 100644 --- a/jenkins/scripts/global-properties.groovy +++ b/jenkins/scripts/global-properties.groovy @@ -10,10 +10,13 @@ * */ import jenkins.model.* +import hudson.markup.RawHtmlMarkupFormatter instance = Jenkins.getInstance() globalNodeProperties = instance.getGlobalNodeProperties() -envVarsNodePropertyList = globalNodeProperties.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class) +envVarsNodePropertyList = + globalNodeProperties.getAll( + hudson.slaves.EnvironmentVariablesNodeProperty.class) def env = System.getenv() @@ -24,6 +27,9 @@ String LOGS_SERVER = env.get('JJB_LOGS_SERVER') String SILO = env.get('JJB_SILO') String JENKINS_HOSTNAME = env.get('JJB_JENKINS_HOSTNAME') +// Set Markup Formatter to 'Safe HTML' so nexus build log links show up. +instance.setMarkupFormatter(new RawHtmlMarkupFormatter(false)) + newEnvVarsNodeProperty = null envVars = null -- 2.16.6