From aae25fc85ee02a784eec9cacae85efc16d890af5 Mon Sep 17 00:00:00 2001 From: Rui Lopes Date: Sun, 27 Nov 2016 13:32:59 +0000 Subject: [PATCH] init --- .gitignore | 3 + README.md | 32 +++ Vagrantfile | 13 ++ provision/execute-provision.groovy-script.sh | 11 ++ provision/nexus-groovy.sh | 31 +++ provision/provision-nexus/Makefile | 17 ++ provision/provision-nexus/README.md | 35 ++++ provision/provision-nexus/pom.xml | 45 +++++ provision/provision-nexus/provision-nexus.iml | 133 +++++++++++++ .../src/main/groovy/deploy.groovy | 12 ++ .../groovy/get-jenkins-nuget-api-key.groovy | 16 ++ .../src/main/groovy/provision.groovy | 117 +++++++++++ provision/provision.sh | 186 ++++++++++++++++++ provision/summary.sh | 18 ++ provision/test.sh | 174 ++++++++++++++++ 15 files changed, 843 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 Vagrantfile create mode 100644 provision/execute-provision.groovy-script.sh create mode 100644 provision/nexus-groovy.sh create mode 100644 provision/provision-nexus/Makefile create mode 100644 provision/provision-nexus/README.md create mode 100644 provision/provision-nexus/pom.xml create mode 100644 provision/provision-nexus/provision-nexus.iml create mode 100644 provision/provision-nexus/src/main/groovy/deploy.groovy create mode 100644 provision/provision-nexus/src/main/groovy/get-jenkins-nuget-api-key.groovy create mode 100644 provision/provision-nexus/src/main/groovy/provision.groovy create mode 100644 provision/provision.sh create mode 100644 provision/summary.sh create mode 100644 provision/test.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5312ec8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vagrant/ +.idea/ +provision/provision-nexus/sources/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..85e5425 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +This is a Vagrant Environment for a [Nexus Repository OSS](https://github.com/sonatype/nexus-public) service. + +This will: + +* Configure Nexus through Groovy scripts. + * Create the `adhoc-package` repository. + * Configure the NuGet `nuget-hosted` repository to accept pushing with an API key. + * Schedule a task to remove the old snapshots from the `maven-snapshots` repository. + * Create users and a custom `deployer` role. + * For more details look inside the [provision/provision-nexus](provision/provision-nexus) directory. +* Setup nginx as a Nexus HTTPS proxy and static file server. +* Test the installed repositories by [using and publishing to them](provision/test.sh). + +**NB** If you are new to Groovy, be sure to check the [Groovy Learn X in Y minutes page](https://learnxinyminutes.com/docs/groovy/). + + +# Usage + +Build and install the [Ubuntu Base Box](https://github.com/rgl/ubuntu-vagrant). + +Add the following entry to your `/etc/hosts` file: + +``` +192.168.56.3 nexus.example.com +``` + +Run `vagrant up` to launch the environment. See its output to known how to login at the +[local Nexus home page](https://nexus.example.com) as `admin` (you can also login with +one of the example accounts, e.g. `alice.doe` and password `password`). + +**NB** nginx is setup with a self-signed certificate that you have to trust before being +able to access the local Nexus home page. diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..134105f --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,13 @@ +Vagrant.configure(2) do |config| + config.vm.box = 'ubuntu-16.04-amd64' + config.vm.hostname = 'nexus.example.com' + config.vm.network 'private_network', ip: '192.168.56.3' + config.vm.provider 'virtualbox' do |vb| + vb.linked_clone = true + vb.cpus = 2 + vb.memory = 4096 + end + config.vm.provision :shell, path: 'provision/provision.sh' + config.vm.provision :shell, path: 'provision/test.sh' + config.vm.provision :shell, path: 'provision/summary.sh' +end diff --git a/provision/execute-provision.groovy-script.sh b/provision/execute-provision.groovy-script.sh new file mode 100644 index 0000000..226c6dd --- /dev/null +++ b/provision/execute-provision.groovy-script.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -eux + +. /vagrant/provision/nexus-groovy.sh + +# list existing scripts. +#http -a "$admin_username:$admin_password" http://localhost:8081/service/siesta/rest/v1/script | jq . + +# run the provision script. +response=$(nexus-groovy provision) +echo "$response" | jq '.result | fromjson' diff --git a/provision/nexus-groovy.sh b/provision/nexus-groovy.sh new file mode 100644 index 0000000..f124e83 --- /dev/null +++ b/provision/nexus-groovy.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -eux + +admin_username=${admin_username:-admin} +admin_password=${admin_password:-admin123} + +# see https://books.sonatype.com/nexus-book/3.0/reference/scripting.html +function nexus-groovy { + local source_filename="/vagrant/provision/provision-nexus/src/main/groovy/$1.groovy" + + local delete_result=$(http \ + -a "$admin_username:$admin_password" \ + --ignore-stdin \ + DELETE http://localhost:8081/service/siesta/rest/v1/script/provision.groovy) + + local create_result=$(http \ + -a "$admin_username:$admin_password" \ + --ignore-stdin \ + --check-status \ + POST http://localhost:8081/service/siesta/rest/v1/script \ + name=provision.groovy \ + type=groovy \ + "content=@$source_filename") + + http \ + -a "$admin_username:$admin_password" \ + --ignore-stdin \ + --check-status \ + POST http://localhost:8081/service/siesta/rest/v1/script/provision.groovy/run \ + Content-Type:text/plain +} diff --git a/provision/provision-nexus/Makefile b/provision/provision-nexus/Makefile new file mode 100644 index 0000000..e2898d8 --- /dev/null +++ b/provision/provision-nexus/Makefile @@ -0,0 +1,17 @@ +sources: sources-download + mkdir -p sources + cd sources && \ + find ~/.m2/repository/org/sonatype/nexus \ + -name '*-sources.jar' \ + -exec bash -c 'mkdir -p "$$(basename {})"' \; \ + -exec bash -c '7z -y "-o$$(basename {})" x {}' \; + #find sources -type f -name '*.groovy' + #grep -r 'NuGet API-Key Realm' sources + +sources-download: + mvn dependency:sources + +clean: + rm -rf sources + +.PHONY: sources sources-download clean diff --git a/provision/provision-nexus/README.md b/provision/provision-nexus/README.md new file mode 100644 index 0000000..7736997 --- /dev/null +++ b/provision/provision-nexus/README.md @@ -0,0 +1,35 @@ +Open this directory with [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download/#section=windows). + +Inside IDEA you can browse the sources with `control+left-click` to see which methods are available. + +To execute the `src/main/groovy/provision.groovy` file inside the Vagrant +environment run `bash /vagrant/execute-provision.groovy-script.sh`. + +For more information see the Nexus [scripting documentation](https://books.sonatype.com/nexus-book/3.0/reference/scripting.html) and [examples](https://github.com/sonatype/nexus-book-examples/tree/nexus-3.0.x/scripting). + +# Source Code + +Run `make sources` to download and extract all the source code into the `sources` directory. + +You are now able to `find` and `grep` it. + +For example, list all `.groovy` files: + +```sh +find sources -type f -name '*groovy' +``` + +Get all exposed API objects: + +```sh +grep -ri ApiImpl sources +``` + +Where you can see the definition of the global variables that are available on a groovy script: + +``` +sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'security', type: 'org.sonatype.nexus.security.internal.SecurityApiImpl' +sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'core', type: 'org.sonatype.nexus.internal.provisioning.CoreApiImpl' +sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'repository', type: 'org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl' +sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'blobStore', type: 'org.sonatype.nexus.internal.provisioning.BlobStoreApiImpl' +``` diff --git a/provision/provision-nexus/pom.xml b/provision/provision-nexus/pom.xml new file mode 100644 index 0000000..6d09f02 --- /dev/null +++ b/provision/provision-nexus/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + com.example.automation + provision-nexus + 1.0-SNAPSHOT + + + 3.1.0-04 + + + + org.sonatype.nexus + nexus-core + ${nx-version} + + + org.sonatype.nexus + nexus-script + ${nx-version} + + + org.sonatype.nexus + nexus-security + ${nx-version} + + + org.sonatype.nexus + nexus-repository + ${nx-version} + + + org.sonatype.nexus.plugins + nexus-repository-maven + ${nx-version} + + + org.sonatype.nexus.plugins + nexus-script-plugin + ${nx-version} + + + \ No newline at end of file diff --git a/provision/provision-nexus/provision-nexus.iml b/provision/provision-nexus/provision-nexus.iml new file mode 100644 index 0000000..2537107 --- /dev/null +++ b/provision/provision-nexus/provision-nexus.iml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/provision/provision-nexus/src/main/groovy/deploy.groovy b/provision/provision-nexus/src/main/groovy/deploy.groovy new file mode 100644 index 0000000..d939ae7 --- /dev/null +++ b/provision/provision-nexus/src/main/groovy/deploy.groovy @@ -0,0 +1,12 @@ +import org.sonatype.nexus.security.user.UserSearchCriteria + +// delete all users except the allowed ones. +allowedUsers = [ + "anonymous", + "admin", + "jenkins", +] +security.securitySystem + .searchUsers(new UserSearchCriteria()) + .findAll { !allowedUsers.contains(it.userId) } + .forEach { security.securitySystem.deleteUser(it.userId) } diff --git a/provision/provision-nexus/src/main/groovy/get-jenkins-nuget-api-key.groovy b/provision/provision-nexus/src/main/groovy/get-jenkins-nuget-api-key.groovy new file mode 100644 index 0000000..53d6b1e --- /dev/null +++ b/provision/provision-nexus/src/main/groovy/get-jenkins-nuget-api-key.groovy @@ -0,0 +1,16 @@ +import groovy.json.JsonOutput +import org.sonatype.nexus.security.authc.apikey.ApiKeyStore +import org.apache.shiro.subject.SimplePrincipalCollection + +def getNuGetApiKey(String userName) { + realmName = "NexusAuthenticatingRealm" + apiKeyDomain = "NuGetApiKey" + principal = new SimplePrincipalCollection(userName, realmName) + keyStore = container.lookup(ApiKeyStore.class.getName()) + apiKey = keyStore.getApiKey(apiKeyDomain, principal) + return apiKey.toString() +} + +return JsonOutput.toJson([ + apiKey: getNuGetApiKey("jenkins"), +]) diff --git a/provision/provision-nexus/src/main/groovy/provision.groovy b/provision/provision-nexus/src/main/groovy/provision.groovy new file mode 100644 index 0000000..c7c12f8 --- /dev/null +++ b/provision/provision-nexus/src/main/groovy/provision.groovy @@ -0,0 +1,117 @@ +// run this file inside the Vagrant environment with bash /vagrant/execute-provision.groovy-script.sh +// see https://books.sonatype.com/nexus-book/3.0/reference/scripting.html +// see https://github.com/sonatype/nexus-book-examples/tree/nexus-3.0.x/scripting/nexus-script-example + +import groovy.json.JsonOutput +import org.sonatype.nexus.security.user.UserSearchCriteria +import org.sonatype.nexus.security.authc.apikey.ApiKeyStore +import org.sonatype.nexus.security.realm.RealmManager +import org.apache.shiro.subject.SimplePrincipalCollection +import org.sonatype.nexus.scheduling.TaskScheduler +import org.sonatype.nexus.scheduling.schedule.Daily + +// create a raw repository backed by the default blob store. +// see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.0.x/scripting/complex-script/rawRepositories.groovy +// see https://books.sonatype.com/nexus-book/3.0/reference/raw.html#_uploading_files_to_hosted_raw_repositories +repository.createRawHosted("adhoc-package", "default") + + +// see http://stackoverflow.com/questions/8138164/groovy-generate-random-string-from-given-character-set +def random(String alphabet, int n) { + new Random().with { + (1..n).collect { alphabet[nextInt(alphabet.length())] }.join() + } +} +jenkinsPassword = random((('A'..'Z')+('a'..'z')+('0'..'9')).join(), 16) + + +// set the base url. this is used when sending emails. +// see https://books.sonatype.com/nexus-book/3.0/reference/admin.html#admin-base-url +core.baseUrl("https://" + java.net.InetAddress.getLocalHost().getCanonicalHostName()) + + +// schedule a task to remove old snapshots from the maven-snapshots repository. +// see https://github.com/sonatype/nexus-public/blob/555cc59e7fa659c0a1a4fbc881bf3fcef0e9a5b6/components/nexus-scheduling/src/main/java/org/sonatype/nexus/scheduling/TaskScheduler.java +// see https://github.com/sonatype/nexus-public/blob/555cc59e7fa659c0a1a4fbc881bf3fcef0e9a5b6/plugins/nexus-coreui-plugin/src/main/java/org/sonatype/nexus/coreui/TaskComponent.groovy +taskScheduler = (TaskScheduler)container.lookup(TaskScheduler.class.getName()) +taskConfiguration = taskScheduler.createTaskConfigurationInstance("repository.maven.remove-snapshots") +taskConfiguration.name = "remove old snapshots from the maven-snapshots repository" +// NB to see the available properties uncomment the tasksDescriptors property from JsonOutput.toJson at the end of this script. +taskConfiguration.setString("repositoryName", "maven-snapshots") +taskConfiguration.setString("minimumRetained", "1") +taskConfiguration.setString("snapshotRetentionDays", "30") +// TODO taskConfiguration.setAlertEmail("TODO") +taskScheduler.scheduleTask(taskConfiguration, new Daily(new Date().clearTime().next())) + + +// enable the NuGet API-Key Realm. +realmManager = container.lookup(RealmManager.class.getName()) +realmManager.enableRealm("NuGetApiKey") + + +// the intent is to get or create an NuGet API Key like the one we can see on the user page: +// http://nexus.example.com:8081/#user/nugetapitoken. +def getOrCreateNuGetApiKey(String userName) { + realmName = "NexusAuthenticatingRealm" + apiKeyDomain = "NuGetApiKey" + principal = new SimplePrincipalCollection(userName, realmName) + keyStore = container.lookup(ApiKeyStore.class.getName()) + apiKey = keyStore.getApiKey(apiKeyDomain, principal) + if (apiKey == null) { + apiKey = keyStore.createApiKey(apiKeyDomain, principal) + } + return apiKey.toString() +} + + +// create users in the deployer role. +// see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.0.x/scripting/complex-script/security.groovy#L38 +def addDeployerUser(firstName, lastName, email, userName, password) { + if (!security.securitySystem.listRoles().any { it.getRoleId() == "deployer" }) { + privileges = [ + "nx-search-read", + "nx-repository-view-*-*-read", + "nx-repository-view-*-*-browse", + "nx-repository-view-*-*-add", + "nx-repository-view-*-*-edit", + "nx-apikey-all"] + security.addRole("deployer", "deployer", "deployment on all repositories", privileges, []) + } + try { + user = security.securitySystem.getUser(userName); + } catch (org.sonatype.nexus.security.user.UserNotFoundException e) { + user = security.addUser(userName, firstName, lastName, email, true, password, ["deployer"]) + } + nuGetApiKey = getOrCreateNuGetApiKey(userName) +} +addDeployerUser("Jenkins", "Doe", "jenkins@example.com", "jenkins", jenkinsPassword) +addDeployerUser("Alice", "Doe", "alice.doe@example.com", "alice.doe", "password") +addDeployerUser("Bob", "Doe", "bob.doe@example.com", "bob.doe", "password") + + +// get the jenkins NuGet API Key. +jenkinsNuGetApiKey = getOrCreateNuGetApiKey("jenkins") + +realms = realmManager.getConfiguration().getRealmNames() +users = security.securitySystem.searchUsers(new UserSearchCriteria()) +repositories = repository.repositoryManager.browse().collect { [name:it.name,type:it.type.value] } + +return JsonOutput.toJson([ + /*tasksDescriptors: taskScheduler.taskFactory.descriptors.collect { [ + id: it.id, + name: it.name, + exposed: it.exposed, + formFields: it.formFields?.collect { [ + id: it.id, + type: it.type, + label: it.label, + helpText: it.helpText, + required: it.required, + regexValidation: it.regexValidation, + initialValue: it.initialValue, + ] } + ] },*/ + realms: realms.sort { it }, + users: users.sort { it.userId }, + repositories: repositories.sort { it.name }, +]) diff --git a/provision/provision.sh b/provision/provision.sh new file mode 100644 index 0000000..cb8ef5b --- /dev/null +++ b/provision/provision.sh @@ -0,0 +1,186 @@ +#!/bin/bash +# here be dragons... see http://fvue.nl/wiki/Bash:_Error_handling +set -eux + +config_fqdn=$(hostname --fqdn) +config_domain=$(hostname --domain) + +echo "127.0.0.1 $config_fqdn" >>/etc/hosts + + +# update the package cache. +apt-get -y update + + +# vim. +apt-get install -y --no-install-recommends vim +cat >/etc/vim/vimrc.local <<'EOF' +syntax on +set background=dark +set esckeys +set ruler +set laststatus=2 +set nobackup +autocmd BufNewFile,BufRead Vagrantfile set ft=ruby +EOF + + +# create a self-signed certificate. +pushd /etc/ssl/private +openssl genrsa \ + -out $config_fqdn-keypair.pem \ + 2048 \ + 2>/dev/null +chmod 400 $config_fqdn-keypair.pem +openssl req -new \ + -sha256 \ + -subj "/CN=$config_fqdn" \ + -key $config_fqdn-keypair.pem \ + -out $config_fqdn-csr.pem +openssl x509 -req -sha256 \ + -signkey $config_fqdn-keypair.pem \ + -extensions a \ + -extfile <(echo "[a] + subjectAltName=DNS:$config_fqdn + extendedKeyUsage=serverAuth + ") \ + -days 365 \ + -in $config_fqdn-csr.pem \ + -out $config_fqdn-crt.pem +popd + + +# install and configure nginx to proxy to nexus. +# see https://books.sonatype.com/nexus-book/3.0/reference/install.html#reverse-proxy +apt-get install -y --no-install-recommends nginx +rm -f /etc/nginx/sites-enabled/default +cat</etc/nginx/sites-available/$config_fqdn.conf +ssl_session_cache shared:SSL:4m; +ssl_session_timeout 6h; +#ssl_stapling on; +#ssl_stapling_verify on; + +server { + listen 80; + server_name _; + return 301 https://$config_fqdn\$request_uri; +} + +server { + listen 443 ssl http2; + server_name $config_fqdn; + access_log /var/log/nginx/$config_fqdn.access.log; + + ssl_certificate /etc/ssl/private/$config_fqdn-crt.pem; + ssl_certificate_key /etc/ssl/private/$config_fqdn-keypair.pem; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + # see https://github.com/cloudflare/sslconfig/blob/master/conf + # see https://blog.cloudflare.com/it-takes-two-to-chacha-poly/ + # see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/ + # NB even though we have CHACHA20 here, the OpenSSL library that ships with Ubuntu 16.04 does not have it. so this is a nop. no problema. + ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!aNULL:!MD5; + + tcp_nodelay on; + client_max_body_size 1G; + proxy_send_timeout 120; + proxy_read_timeout 300; + proxy_buffering off; + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_set_header Host \$host; + proxy_set_header X-Forwarded-Host \$host; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + + location / { + root /opt/nexus/public; + try_files \$uri @nexus; + } + + location @nexus { + proxy_pass http://127.0.0.1:8081; + } +} +EOF +ln -s ../sites-available/$config_fqdn.conf /etc/nginx/sites-enabled/ +systemctl restart nginx + + +# install java. +apt-get install -y default-jre + + +# add the nexus user. +groupadd --system nexus +adduser \ + --system \ + --disabled-login \ + --no-create-home \ + --gecos '' \ + --ingroup nexus \ + --home /opt/nexus \ + nexus +install -d -o root -g nexus -m 750 /opt/nexus + + +# download and install nexus. +pushd /opt/nexus +# see http://www.sonatype.com/download-oss-sonatype +# see https://books.sonatype.com/nexus-book/3.0/reference/index.html +nexus_tarball=nexus-3.1.0-04-unix.tar.gz +nexus_download_url=https://sonatype-download.global.ssl.fastly.net/nexus/3/$nexus_tarball +nexus_download_sha1=e42053ba8ab33b3b4f79f7e50dbac2ffe6ca3b6e +wget -q $nexus_download_url +if [ "$(sha1sum $nexus_tarball | awk '{print $1}')" != "$nexus_download_sha1" ]; then + echo "downloaded $nexus_download_url failed the checksum verification" + exit 1 +fi +tar xf $nexus_tarball --strip-components 1 +rm $nexus_tarball +chmod 700 nexus3 +chown -R nexus:nexus nexus3 +chmod 700 etc +chown -R nexus:nexus etc # for some reason karaf changes files inside this directory. TODO see why. +install -d -o nexus -g nexus -m 700 .java # java preferences are saved here (the default java.util.prefs.userRoot preference). +cp -p etc/{nexus-default.properties,nexus.properties} +sed -i -E 's,(application-host=).+,\1127.0.0.1,g' etc/nexus.properties +sed -i -E 's,nexus-pro-,nexus-oss-,g' etc/nexus.properties +sed -i -E 's,\.\./sonatype-work/,,g' bin/nexus.vmoptions +popd + + +# start nexus. +cat >/etc/systemd/system/nexus.service <<'EOF' +[Unit] +Description=Nexus +After=network.target + +[Service] +Type=simple +User=nexus +Group=nexus +ExecStart=/opt/nexus/bin/nexus run +WorkingDirectory=/opt/nexus +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable nexus +systemctl start nexus + +# install tools. +apt-get install -y --no-install-recommends httpie +apt-get install -y --no-install-recommends jq + +# wait for nexus to come up. +bash -c 'while [[ "$(wget -qO- http://localhost:8081/service/extdirect/poll/rapture_State_get | jq -r .data.data.status.value.edition)" != "OSS" ]]; do sleep 5; done' + +# print the version using the API. +wget -qO- http://localhost:8081/service/extdirect/poll/rapture_State_get | jq --raw-output .data.data.uiSettings.value.title +wget -qO- http://localhost:8081/service/extdirect/poll/rapture_State_get | jq .data.data.status.value + +# configure nexus with the groovy script. +bash /vagrant/provision/execute-provision.groovy-script.sh + +# clean packages. +apt-get -y autoremove +apt-get -y clean diff --git a/provision/summary.sh b/provision/summary.sh new file mode 100644 index 0000000..9831b37 --- /dev/null +++ b/provision/summary.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -eux + +config_fqdn=$(hostname --fqdn) + +# show the installation summary. +cat <example-hello-world.nuspec + + + example-hello-world + 1.0.0 + Alice Doe + Bob Doe + http://choosealicense.com/licenses/mit/ + http://example.com + false + Example Package Description + Hello World. + Copyleft Alice Doe + hello world + + + + + +EOF +cat <<'EOF' >MESSAGE.md +# Hello World + +Hey Ho Let's Go! +EOF +nuget pack example-hello-world.nuspec +nuget push example-hello-world.1.0.0.nupkg -Source $nuget_source_push_url -ApiKey $nuget_source_push_api_key +# test installing it back. +rm -rf test && mkdir test && pushd test +nuget install example-hello-world -Source $nuget_source_url +if [[ ! -f example-hello-world.1.0.0/content/MESSAGE.md ]]; then + echo 'the package did not install as expected' + exit 1 +fi +popd + + +# +# test the maven repository. + +# install maven and the java development kit. +sudo apt-get install -y maven +sudo apt-get install -y default-jdk +sudo apt-get install -y xmlstarlet + +# setup the user maven configuration to use nexus as a mirror the +# official maven repository. +# see https://books.sonatype.com/nexus-book/3.0/reference/maven.html +# see https://maven.apache.org/guides/mini/guide-mirror-settings.html +mkdir -p ~/.m2 +cat <<'EOF' >~/.m2/settings.xml + + + + nexus + alice.doe + password + + + + + nexus + central + http://localhost:8081/repository/maven-public/ + + + + + nexus + + + central + http://central + true + true + + + + + central + http://central + true + true + + + + + + nexus + + +EOF + +# test our nexus repository by creating an hello world project, which +# will pull from our nexus repository. +mvn \ + archetype:generate \ + -DgroupId=com.example.helloworld \ + -DartifactId=example-helloworld \ + -DarchetypeArtifactId=maven-archetype-quickstart \ + -DinteractiveMode=false + +# test publishing a package. +pushd example-helloworld +# add the nexus repository to pom.xml. +xmlstarlet ed --inplace -N pom=http://maven.apache.org/POM/4.0.0 \ + --subnode '/pom:project' \ + --type elem \ + --name distributionManagement \ + --value '@@repositories@@' \ + pom.xml +python -c ' +xml = open("pom.xml").read().replace("@@repositories@@", """ + + nexus + Releases + http://localhost:8081/repository/maven-releases + + + nexus + Snapshot + http://localhost:8081/repository/maven-snapshots + + """) +open("pom.xml", "w").write(xml) +' +# deploy. +mvn deploy +popd + + +# +# test the raw repository. + +apt-get install -y curl + +# upload. +# see https://books.sonatype.com/nexus-book/3.0/reference/raw.html#_uploading_files_to_hosted_raw_repositories +expected='this is an adhoc package' +echo "$expected" >package-1.0.0.txt +curl --silent --user 'admin:admin123' --upload-file package-1.0.0.txt http://localhost:8081/repository/adhoc-package/package-1.0.0.txt +# download. +actual=$(curl --silent http://localhost:8081/repository/adhoc-package/package-1.0.0.txt) +[ "$actual" = "$expected" ] || (echo 'upload adhoc package test failed' && false)