You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2019/04/24 12:31:44 UTC
[sling-org-apache-sling-committer-cli] 15/44: SLING-8311 -
Investigate creating a Sling CLI tool for development task automation
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch feature/SLING-8337
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-committer-cli.git
commit 95330f1312369738740edca534816d70e763ccdc
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Thu Mar 28 17:41:06 2019 +0100
SLING-8311 - Investigate creating a Sling CLI tool for development task automation
* added support for updating a release in the Apache Reporter System
* added a service for extracting the user's credentials from the environment
* switched Docker image to the openjdk11 provided by azul
* used jlink to create a minimal JRE
---
Dockerfile | 10 +-
pom.xml | 13 ++-
src/main/features/app.json | 14 +--
.../org/apache/sling/cli/impl/Credentials.java | 38 +++++++
.../apache/sling/cli/impl/CredentialsService.java | 55 +++++++++
.../cli/impl/nexus/StagingRepositoryFinder.java | 32 ++----
.../sling/cli/impl/people/MembersFinder.java | 17 +--
.../cli/impl/release/UpdateReporterCommand.java | 124 +++++++++++++++++++++
src/main/resources/scripts/launcher.sh | 24 ++--
9 files changed, 268 insertions(+), 59 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index c29cd1e..ca438e9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,12 +9,16 @@
# either express or implied. See the License for the specific language governing permissions
# and limitations under the License.
# ----------------------------------------------------------------------------------------
-
-FROM openjdk:8-jre-alpine
+FROM azul/zulu-openjdk-alpine:11 as builder
MAINTAINER dev@sling.apache.org
+RUN jlink --add-modules java.logging,java.naming,java.xml,java.security.jgss,java.sql,jdk.crypto.ec \
+ --output /opt/jre --strip-debug --compress=2 --no-header-files --no-man-pages
+
+FROM alpine
+COPY --from=builder /opt/jre /opt/jre
# Generate class data sharing
-RUN java -Xshare:dump
+RUN /opt/jre/bin/java -Xshare:dump
# escaping required to properly handle arguments with spaces
ENTRYPOINT ["/usr/share/sling-cli/bin/launcher.sh"]
diff --git a/pom.xml b/pom.xml
index 1f717d7..b27394e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,8 +16,8 @@
<parent>
<groupId>org.apache.sling</groupId>
- <artifactId>sling</artifactId>
- <version>34</version>
+ <artifactId>sling-bundle-parent</artifactId>
+ <version>35-SNAPSHOT</version>
<relativePath />
</parent>
@@ -28,6 +28,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <sling.java.version>11</sling.java.version>
</properties>
<build>
@@ -123,6 +124,14 @@
</buildArgs>
</configuration>
</plugin>
+ <plugin>
+ <groupId>biz.aQute.bnd</groupId>
+ <artifactId>bnd-baseline-maven-plugin</artifactId>
+ <configuration>
+ <!-- We don't export an API, so it should be safe to skip baseline. -->
+ <skip>true</skip>
+ </configuration>
+ </plugin>
</plugins>
</build>
diff --git a/src/main/features/app.json b/src/main/features/app.json
index 4d310c4..5fb7cd2 100644
--- a/src/main/features/app.json
+++ b/src/main/features/app.json
@@ -1,9 +1,5 @@
{
"id": "${project.groupId}:${project.artifactId}:slingfeature:app:${project.version}",
- "variables": {
- "asf.username":"change-me",
- "asf.password": "change-me"
- },
"bundles": [
{
"id": "${project.groupId}:${project.artifactId}:${project.version}",
@@ -69,11 +65,5 @@
"id": "org.apache.servicemix.bundles:org.apache.servicemix.bundles.jsch:0.1.55_1",
"start-level": "3"
}
- ],
- "configurations": {
- "org.apache.sling.cli.impl.nexus.StagingRepositoryFinder": {
- "username": "${asf.username}",
- "password": "${asf.password}"
- }
- }
-}
\ No newline at end of file
+ ]
+}
diff --git a/src/main/java/org/apache/sling/cli/impl/Credentials.java b/src/main/java/org/apache/sling/cli/impl/Credentials.java
new file mode 100644
index 0000000..2df5a32
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/Credentials.java
@@ -0,0 +1,38 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.cli.impl;
+
+public class Credentials {
+
+ private final String user;
+ private final String password;
+
+ public Credentials(String user, String password) {
+ this.user = user;
+ this.password = password;
+ }
+
+ public String getUsername() {
+ return user;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
diff --git a/src/main/java/org/apache/sling/cli/impl/CredentialsService.java b/src/main/java/org/apache/sling/cli/impl/CredentialsService.java
new file mode 100644
index 0000000..3ddbcca
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/CredentialsService.java
@@ -0,0 +1,55 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.cli.impl;
+
+import java.util.Optional;
+
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = CredentialsService.class)
+public class CredentialsService {
+
+ private static final String USER_SYS_PROP = "asf.username";
+ private static final String PASSWORD_SYS_PROP = "asf.password";
+ private static final String USER_ENV_PROP = "ASF_USERNAME";
+ private static final String PASSWORD_ENV_PROP = "ASF_PASSWORD";
+
+ private volatile Credentials credentials;
+
+ @Activate
+ private void activate() {
+ Optional<String> username =
+ Optional.ofNullable(System.getProperty(USER_SYS_PROP)).or(() -> Optional.ofNullable(System.getenv(USER_ENV_PROP)));
+ Optional<String> password =
+ Optional.ofNullable(System.getProperty(PASSWORD_SYS_PROP)).or(() -> Optional.ofNullable(System.getenv(PASSWORD_ENV_PROP)));
+ credentials = new Credentials(
+ username.orElseThrow(() -> new IllegalStateException(
+ String.format("Cannot detect user information after looking for %s system property and %s environment variable.",
+ USER_SYS_PROP, USER_ENV_PROP))),
+ password.orElseThrow(() -> new IllegalStateException(
+ String.format("Cannot detect password after looking for %s system property and %s environment variable.",
+ PASSWORD_SYS_PROP, PASSWORD_ENV_PROP)))
+ );
+ }
+
+ public Credentials getCredentials() {
+ return credentials;
+ }
+}
diff --git a/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java b/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java
index 21b30ff..9093a04 100644
--- a/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java
+++ b/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java
@@ -30,45 +30,35 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
+import org.apache.sling.cli.impl.Credentials;
+import org.apache.sling.cli.impl.CredentialsService;
import org.apache.sling.cli.impl.nexus.StagingRepository.Status;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.ConfigurationPolicy;
-import org.osgi.service.metatype.annotations.AttributeDefinition;
-import org.osgi.service.metatype.annotations.Designate;
-import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.osgi.service.component.annotations.Reference;
import com.google.gson.Gson;
-@Component(
- configurationPolicy = ConfigurationPolicy.REQUIRE,
- service = StagingRepositoryFinder.class
-)
-@Designate(ocd = StagingRepositoryFinder.Config.class)
+@Component(service = StagingRepositoryFinder.class)
public class StagingRepositoryFinder {
private static final String REPOSITORY_PREFIX = "orgapachesling-";
- @ObjectClassDefinition
- static @interface Config {
- @AttributeDefinition(name="Username")
- String username();
-
- @AttributeDefinition(name="Password")
- String password();
- }
+ @Reference
+ private CredentialsService credentialsService;
private BasicCredentialsProvider credentialsProvider;
@Activate
- protected void activate(Config cfg) {
+ private void activate() {
+ Credentials credentials = credentialsService.getCredentials();
credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope("repository.apache.org", 443),
- new UsernamePasswordCredentials(cfg.username(), cfg.password()));
+ new UsernamePasswordCredentials(credentials.getUsername(), credentials.getPassword()));
}
public List<StagingRepository> list() throws IOException {
- return this. <List<StagingRepository>> withStagingRepositories( reader -> {
+ return this.withStagingRepositories( reader -> {
Gson gson = new Gson();
return gson.fromJson(reader, StagingRepositories.class).getData().stream()
.filter( r -> r.getType() == Status.closed)
@@ -78,7 +68,7 @@ public class StagingRepositoryFinder {
}
public StagingRepository find(int stagingRepositoryId) throws IOException {
- return this.<StagingRepository> withStagingRepositories( reader -> {
+ return this.withStagingRepositories( reader -> {
Gson gson = new Gson();
return gson.fromJson(reader, StagingRepositories.class).getData().stream()
.filter( r -> r.getType() == Status.closed)
diff --git a/src/main/java/org/apache/sling/cli/impl/people/MembersFinder.java b/src/main/java/org/apache/sling/cli/impl/people/MembersFinder.java
index a27bf6c..70b5469 100644
--- a/src/main/java/org/apache/sling/cli/impl/people/MembersFinder.java
+++ b/src/main/java/org/apache/sling/cli/impl/people/MembersFinder.java
@@ -29,7 +29,9 @@ import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
+import org.apache.sling.cli.impl.CredentialsService;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,6 +49,9 @@ public class MembersFinder {
private Set<Member> members = Collections.emptySet();
private long lastCheck = 0;
+ @Reference
+ private CredentialsService credentialsService;
+
public synchronized Set<Member> findMembers() {
final Set<Member> _members = new HashSet<>();
if (lastCheck == 0 || System.currentTimeMillis() > lastCheck + STALENESS_IN_HOURS * 3600 * 1000) {
@@ -108,17 +113,7 @@ public class MembersFinder {
}
public Member getCurrentMember() {
- final String currentUserId;
- if (System.getProperty("asf.username") != null) {
- currentUserId = System.getProperty("asf.username");
- } else {
- currentUserId = System.getenv("ASF_USERNAME");
- }
- if (currentUserId == null) {
- throw new IllegalStateException(String.format("Expected to find the current user defined either through the %s system " +
- "property or through the %s environment variable.", "asf.username", "ASF_USERNAME"));
- }
- return getMemberById(currentUserId);
+ return getMemberById(credentialsService.getCredentials().getUsername());
}
}
diff --git a/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java b/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java
new file mode 100644
index 0000000..4c0c127
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java
@@ -0,0 +1,124 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.cli.impl.release;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ssl.DefaultHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.sling.cli.impl.Command;
+import org.apache.sling.cli.impl.Credentials;
+import org.apache.sling.cli.impl.CredentialsService;
+import org.apache.sling.cli.impl.nexus.StagingRepository;
+import org.apache.sling.cli.impl.nexus.StagingRepositoryFinder;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = Command.class,
+ property = {
+ Command.PROPERTY_NAME_COMMAND + "=release",
+ Command.PROPERTY_NAME_SUBCOMMAND + "=update-reporter",
+ Command.PROPERTY_NAME_SUMMARY + "=Updates the Apache Reporter System with the new release information"
+ }
+)
+public class UpdateReporterCommand implements Command {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(UpdateReporterCommand.class);
+
+ @Reference
+ private StagingRepositoryFinder repoFinder;
+
+ @Reference
+ private CredentialsService credentialsService;
+
+ private CredentialsProvider credentialsProvider;
+
+ @Override
+ public void execute(String target) {
+ try {
+ StagingRepository repository = repoFinder.find(Integer.parseInt(target));
+ Release release = Release.fromString(repository.getDescription());
+ SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+ sslContext.init(null, null, null);
+ SSLContext.setDefault(sslContext);
+ SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
+ sslContext,
+ new String[] {"TLSv1.2"},
+ new String[] {
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
+ },
+ new DefaultHostnameVerifier()
+ );
+ try (CloseableHttpClient client =
+ HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).setSSLSocketFactory(sslConnectionSocketFactory).build()) {
+ HttpPost post = new HttpPost("https://reporter.apache.org/addrelease.py");
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ List<NameValuePair> parameters = new ArrayList<>();
+ Date now = new Date();
+ parameters.add(new BasicNameValuePair("date", Long.toString(now.getTime() / 1000)));
+ parameters.add(new BasicNameValuePair("committee", "sling"));
+ parameters.add(new BasicNameValuePair("version", release.getFullName()));
+ parameters.add(new BasicNameValuePair("xdate", simpleDateFormat.format(now)));
+ post.setEntity(new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8));
+ try (CloseableHttpResponse response = client.execute(post)) {
+ if (response.getStatusLine().getStatusCode() != 200) {
+ throw new IOException(String.format("The Apache Reporter System update failed. Got response code %s instead of " +
+ "200.", response.getStatusLine().getStatusCode()));
+ }
+ }
+ }
+ } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
+ LOGGER.error(String.format("Unable to update reporter service; passed command: %s.", target), e);
+ }
+
+ }
+
+ @Activate
+ private void activate() {
+ Credentials credentials = credentialsService.getCredentials();
+ credentialsProvider = new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(new AuthScope("reporter.apache.org", 443),
+ new UsernamePasswordCredentials(credentials.getUsername(), credentials.getPassword()));
+ }
+}
diff --git a/src/main/resources/scripts/launcher.sh b/src/main/resources/scripts/launcher.sh
index 7b306ba..08f103f 100755
--- a/src/main/resources/scripts/launcher.sh
+++ b/src/main/resources/scripts/launcher.sh
@@ -18,13 +18,17 @@
ARGS_PROP="exec.args=$@"
# Use exec to become pid 1, see https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
-exec /usr/bin/java \
- -Xshare:on \
- -Dorg.slf4j.simpleLogger.logFile=/dev/null \
- -Dlogback.configurationFile=file:/usr/share/sling-cli/conf/logback-default.xml \
- -jar /usr/share/sling-cli/launcher/org.apache.sling.feature.launcher.jar \
- -f /usr/share/sling-cli/sling-cli.feature \
- -c /usr/share/sling-cli/artifacts \
- -D "$ARGS_PROP" \
- -V "asf.username=${ASF_USERNAME}" \
- -V "asf.password=${ASF_PASSWORD}"
+exec /opt/jre/bin/java \
+ --add-opens=java.base/java.lang=ALL-UNNAMED \
+ --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED \
+ --add-opens=java.base/java.net=ALL-UNNAMED \
+ --add-opens=java.base/java.security=ALL-UNNAMED \
+ -Xshare:on \
+ -Dorg.slf4j.simpleLogger.logFile=/dev/null \
+ -Dlogback.configurationFile=file:/usr/share/sling-cli/conf/logback-default.xml \
+ -jar /usr/share/sling-cli/launcher/org.apache.sling.feature.launcher.jar \
+ -f /usr/share/sling-cli/sling-cli.feature \
+ -c /usr/share/sling-cli/artifacts \
+ -D "$ARGS_PROP" \
+ -V "asf.username=${ASF_USERNAME}" \
+ -V "asf.password=${ASF_PASSWORD}"