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:32:06 UTC

[sling-org-apache-sling-committer-cli] 37/44: SLING-8337 - Create sub-command to manage the Jira update when promoting a release

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 7deca18cc89a9f6b1c7eff019ce87c04c0d441cc
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Apr 23 16:14:37 2019 +0300

    SLING-8337 - Create sub-command to manage the Jira update when promoting
    a release
    
    Move the VersionClient to be an HTTP-based test in preparation for
    testing commands that change state.
---
 pom.xml                                            |  9 +--
 .../sling/cli/impl/ComponentContextHelper.java     | 47 ++++++++++++
 .../sling/cli/impl/http/HttpClientFactory.java     | 17 ++++-
 .../apache/sling/cli/impl/jira/VersionClient.java  | 28 ++++---
 .../org/apache/sling/cli/impl/jira/MockJira.java   | 86 ++++++++++++++++++++++
 .../sling/cli/impl/jira/VersionClientTest.java     | 50 +++----------
 6 files changed, 182 insertions(+), 55 deletions(-)

diff --git a/pom.xml b/pom.xml
index 6fa560a..bf1224a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,6 +164,10 @@
             <artifactId>osgi.core</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature.launcher</artifactId>
             <version>0.8.0</version>
@@ -231,10 +235,5 @@
             <version>1.3.0</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>osgi.cmpn</artifactId>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/cli/impl/ComponentContextHelper.java b/src/main/java/org/apache/sling/cli/impl/ComponentContextHelper.java
new file mode 100644
index 0000000..b996e88
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/ComponentContextHelper.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.osgi.service.component.ComponentContext;
+
+public class ComponentContextHelper {
+
+    public static ComponentContextHelper wrap(ComponentContext wrapped) {
+   
+        return new ComponentContextHelper(wrapped);
+    }
+
+    private final ComponentContext wrapped;
+
+    public ComponentContextHelper(ComponentContext wrapped) {
+        this.wrapped = wrapped;
+    }
+    
+    public String getProperty(String name, String fallback) {
+        Object prop = wrapped.getProperties().get(name);
+        if ( prop != null) {
+            return prop.toString();
+        }
+        
+        return fallback;
+    }
+    
+    public int getProperty(String name, int fallback) {
+        
+        return Integer.parseInt(getProperty(name, String.valueOf(fallback)));
+    }
+}
diff --git a/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java b/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java
index 7975145..f881594 100644
--- a/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java
+++ b/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java
@@ -21,16 +21,31 @@ import org.apache.http.auth.UsernamePasswordCredentials;
 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.ComponentContextHelper;
 import org.apache.sling.cli.impl.Credentials;
 import org.apache.sling.cli.impl.CredentialsService;
+import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 
 @Component(service = HttpClientFactory.class)
 public class HttpClientFactory {
     
+    private static final String DEFAULT_JIRA_HOST = "jira.apache.org";
+    private static final int DEFAULT_JIRA_PORT = 443;
+    
     @Reference
     private CredentialsService credentialsService;
+    
+    private String jiraHost;
+    private int jiraPort;
+    
+    protected void activate(ComponentContext ctx) {
+        
+        ComponentContextHelper helper = ComponentContextHelper.wrap(ctx);
+        jiraHost = helper.getProperty("jira.host", DEFAULT_JIRA_HOST);
+        jiraPort = helper.getProperty("jira.port", DEFAULT_JIRA_PORT);
+    }
 
     public CloseableHttpClient newClient() {
         
@@ -42,7 +57,7 @@ public class HttpClientFactory {
                 new UsernamePasswordCredentials(asf.getUsername(), asf.getPassword()));
         credentialsProvider.setCredentials(new AuthScope("reporter.apache.org", 443), 
                 new UsernamePasswordCredentials(asf.getUsername(), asf.getPassword()));
-        credentialsProvider.setCredentials(new AuthScope("jira.apache.org", 443), 
+        credentialsProvider.setCredentials(new AuthScope(jiraHost, jiraPort), 
                 new UsernamePasswordCredentials(jira.getUsername(), jira.getPassword()));
         
         return HttpClients.custom()
diff --git a/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java b/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java
index 77e6881..0c11c3c 100644
--- a/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java
+++ b/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java
@@ -32,8 +32,10 @@ import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.sling.cli.impl.ComponentContextHelper;
 import org.apache.sling.cli.impl.http.HttpClientFactory;
 import org.apache.sling.cli.impl.release.Release;
+import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 
@@ -47,11 +49,17 @@ import com.google.gson.stream.JsonWriter;
 @Component(service = VersionClient.class)
 public class VersionClient {
     
-    private static final String JIRA_URL_PREFIX = "https://issues.apache.org/jira/rest/api/2/";
+    private static final String DEFAULT_JIRA_URL_PREFIX = "https://issues.apache.org/jira/rest/api/2/";
     private static final String CONTENT_TYPE_JSON = "application/json";
     
     @Reference
     private HttpClientFactory httpClientFactory;
+    private String jiraUrlPrefix;
+    
+    protected void activate(ComponentContext ctx) {
+        ComponentContextHelper helper = ComponentContextHelper.wrap(ctx);
+        jiraUrlPrefix = helper.getProperty("jira.url.prefix", DEFAULT_JIRA_URL_PREFIX);
+    }
 
     /**
      * Finds a Jira version which matches the specified release
@@ -98,12 +106,8 @@ public class VersionClient {
         
         try (CloseableHttpClient client = httpClientFactory.newClient()) {
             Optional<Version> opt = findVersion ( 
-                    v -> {
-                        Release releaseFromVersion = Release.fromString(v.getName()).get(0);
-                        return 
-                            releaseFromVersion.getComponent().equals(release.getComponent())
-                                && new org.osgi.framework.Version(releaseFromVersion.getVersion()).compareTo(new org.osgi.framework.Version(release.getVersion())) > 0;
-                    },client);
+                    v -> isFollowingVersion(Release.fromString(v.getName()).get(0), release)
+                    ,client);
             if ( !opt.isPresent() )
                 return null;
             version = opt.get();
@@ -115,6 +119,12 @@ public class VersionClient {
         return version;
     }
     
+    private boolean isFollowingVersion(Release base, Release candidate) {
+        return base.getComponent().equals(candidate.getComponent())
+                && new org.osgi.framework.Version(base.getVersion())
+                    .compareTo(new org.osgi.framework.Version(candidate.getVersion())) > 0;
+    }
+    
     public void create(String versionName) throws IOException {
         StringWriter w = new StringWriter();
         try ( JsonWriter jw = new Gson().newJsonWriter(w) ) {
@@ -124,7 +134,7 @@ public class VersionClient {
             jw.endObject();
         }
         
-        HttpPost post = new HttpPost(JIRA_URL_PREFIX + "version");
+        HttpPost post = new HttpPost(jiraUrlPrefix + "version");
         post.addHeader("Content-Type", CONTENT_TYPE_JSON);
         post.addHeader("Accept", CONTENT_TYPE_JSON);
         post.setEntity(new StringEntity(w.toString()));
@@ -190,7 +200,7 @@ public class VersionClient {
     }
     
     private HttpGet newGet(String suffix) {
-        HttpGet get = new HttpGet(JIRA_URL_PREFIX + suffix);
+        HttpGet get = new HttpGet(jiraUrlPrefix + suffix);
         get.addHeader("Accept", CONTENT_TYPE_JSON);
         return get;
     }
diff --git a/src/test/java/org/apache/sling/cli/impl/jira/MockJira.java b/src/test/java/org/apache/sling/cli/impl/jira/MockJira.java
new file mode 100644
index 0000000..903f8b0
--- /dev/null
+++ b/src/test/java/org/apache/sling/cli/impl/jira/MockJira.java
@@ -0,0 +1,86 @@
+/*
+ * 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.jira;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.rules.ExternalResource;
+
+import com.sun.net.httpserver.HttpServer;
+
+public class MockJira extends ExternalResource {
+    
+    private static final Pattern VERSION_RELATED_ISSUES = Pattern.compile("^/jira/rest/api/2/version/(\\d+)/relatedIssueCounts$");
+    
+    public static void main(String[] args) throws Throwable {
+        
+        MockJira mj = new MockJira();
+        mj.before();
+        System.out.println(mj.getBoundPort());
+    }
+
+    private HttpServer server;
+    
+    @Override
+    protected void before() throws Throwable {
+        server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
+        server.createContext("/", httpExchange -> {
+            
+            if ( httpExchange.getRequestURI().getPath().equals("/jira/rest/api/2/project/SLING/versions") ) {
+                httpExchange.sendResponseHeaders(200, 0);
+                try ( InputStream in = getClass().getResourceAsStream("/jira/versions.json");
+                        OutputStream out = httpExchange.getResponseBody() ) {
+                    IOUtils.copy(in, out);
+                }
+            } else {
+                Matcher matcher = VERSION_RELATED_ISSUES.matcher(httpExchange.getRequestURI().getPath());
+                if ( matcher.matches() ) {
+                    int version = Integer.parseInt(matcher.group(1));
+                    InputStream in = getClass().getResourceAsStream("/jira/relatedIssueCounts/" + version + ".json");
+                    if ( in == null  ) {
+                        httpExchange.sendResponseHeaders(404, -1);
+                    } else {
+                        httpExchange.sendResponseHeaders(200, 0);
+                        try ( OutputStream out = httpExchange.getResponseBody() ) {
+                            IOUtils.copy(in, out);
+                        }
+                    }
+                } else {
+                    httpExchange.sendResponseHeaders(400, -1);
+                }
+            }
+        });
+        
+        server.start();
+    }
+    
+    @Override
+    protected void after() {
+        
+        server.stop(0);
+    }
+    
+    public int getBoundPort() {
+        
+        return server.getAddress().getPort();
+    }
+}
diff --git a/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java b/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java
index 0cac72d..0d67dee 100644
--- a/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java
@@ -21,15 +21,9 @@ import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
 import static org.junit.Assert.assertThat;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.Field;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.function.Function;
 
-import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.sling.cli.impl.CredentialsService;
 import org.apache.sling.cli.impl.http.HttpClientFactory;
 import org.apache.sling.cli.impl.release.Release;
@@ -42,10 +36,10 @@ public class VersionClientTest {
 
     private static final Map<String, String> SYSTEM_PROPS = new HashMap<>();
     static {
-        SYSTEM_PROPS.put("asf.username", "user");
-        SYSTEM_PROPS.put("asf.password", "password");
-        SYSTEM_PROPS.put("jira.username", "user");
-        SYSTEM_PROPS.put("jira.password", "password");
+        SYSTEM_PROPS.put("asf.username", "asf-user");
+        SYSTEM_PROPS.put("asf.password", "asf-password");
+        SYSTEM_PROPS.put("jira.username", "jira-user");
+        SYSTEM_PROPS.put("jira.password", "jira-password");
     }
     
     @Rule
@@ -54,17 +48,17 @@ public class VersionClientTest {
     @Rule
     public final SystemPropertiesRule sysProps = new SystemPropertiesRule(SYSTEM_PROPS);
     
+    @Rule
+    public final MockJira mockJira = new MockJira();
+    
     private VersionClient versionClient;
     
     @Before
     public void prepareDependencies() throws ReflectiveOperationException {
-        context.registerInjectActivateService(new CredentialsService());
-        context.registerInjectActivateService(new HttpClientFactory());
         
-        versionClient = new StubVersionClient();
-        Field factoryField = VersionClient.class.getDeclaredField("httpClientFactory");
-        factoryField.setAccessible(true);
-        factoryField.set(versionClient, context.getService(HttpClientFactory.class));
+        context.registerInjectActivateService(new CredentialsService());
+        context.registerInjectActivateService(new HttpClientFactory(), "jira.host", "localhost", "jira.port", mockJira.getBoundPort());
+        versionClient = context.registerInjectActivateService(new VersionClient(), "jira.url.prefix", "http://localhost:" + mockJira.getBoundPort() + "/jira/rest/api/2/");
     }
     
     @Test
@@ -98,28 +92,4 @@ public class VersionClientTest {
         
         assertThat("successor", successor, nullValue());
     }
-    
-    private static final class StubVersionClient extends VersionClient {
-        @Override
-        protected <T> T doWithJiraVersions(CloseableHttpClient client, Function<InputStreamReader, T> parserCallback)
-                throws IOException {
-            
-            try ( InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/jira/versions.json")) ) {
-                return parserCallback.apply(reader);
-            }
-        }
-        
-        @Override
-        protected <T> T doWithRelatedIssueCounts(CloseableHttpClient client, Version version,
-                Function<InputStreamReader, T> parserCallback) throws IOException {
-            
-            InputStream stream = getClass().getResourceAsStream("/jira/relatedIssueCounts/" + version.getId()+".json");
-            if ( stream == null )
-                throw new IllegalArgumentException("No related issues count for version " + version.getId() + " (" + version.getName() + ")");
-            
-            try ( InputStreamReader reader = new InputStreamReader(stream) ) {
-                return parserCallback.apply(reader);
-            }
-        }
-    }
 }