{"action":"created","comment":{"url":"https://api.github.com/repos/apache/stratos/pulls/comments/36712101","id":36712101,"diff_hunk":"@@ -0,0 +1,588 @@\n+/*\n+ * Licensed to the Apache Software Foundation (ASF) under one\n+ * or more contributor license agreements.  See the NOTICE file\n+ * distributed with this work for additional information\n+ * regarding copyright ownership.  The ASF licenses this file\n+ * to you under the Apache License, Version 2.0 (the\n+ * \"License\"); you may not use this file except in compliance\n+ * with the License.  You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing,\n+ * software distributed under the License is distributed on an\n+ * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n+ * KIND, either express or implied.  See the License for the\n+ * specific language governing permissions and limitations\n+ * under the License.\n+ */\n+\n+package org.apache.stratos.gce.extension.util;\n+\n+import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;\n+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;\n+import com.google.api.client.http.HttpTransport;\n+import com.google.api.client.json.JsonFactory;\n+import com.google.api.client.json.jackson2.JacksonFactory;\n+import com.google.api.services.compute.Compute;\n+import com.google.api.services.compute.ComputeScopes;\n+import com.google.api.services.compute.model.*;\n+import org.apache.commons.logging.Log;\n+import org.apache.commons.logging.LogFactory;\n+import org.apache.stratos.gce.extension.config.GCEContext;\n+import org.apache.stratos.load.balancer.extension.api.exception.LoadBalancerExtensionException;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.security.GeneralSecurityException;\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.List;\n+\n+/**\n+ * All the GCE API calls will be done using this class\n+ */\n+public class GCEOperations {\n+    private static final Log log = LogFactory.getLog(GCEOperations.class);\n+\n+    //project related\n+    private static final String PROJECT_NAME = GCEContext.getInstance().getProjectName();\n+    private static final String PROJECT_ID = GCEContext.getInstance().getProjectID();\n+    private static final String REGION_NAME = GCEContext.getInstance().getRegionName();\n+\n+    //auth\n+    private static final String KEY_FILE_PATH = GCEContext.getInstance().getKeyFilePath();\n+    private static final String ACCOUNT_ID = GCEContext.getInstance().getGceAccountID();\n+\n+    //health check\n+    private static final String HEALTH_CHECK_REQUEST_PATH = GCEContext.getInstance().getHealthCheckRequestPath();\n+    private static final String HEALTH_CHECK_PORT = GCEContext.getInstance().getHealthCheckPort();\n+    private static final String HEALTH_CHECK_TIME_OUT_SEC = GCEContext.getInstance().getHealthCheckTimeOutSec();\n+    private static final String HEALTH_CHECK_INTERVAL_SEC = GCEContext.getInstance().getHealthCheckIntervalSec();\n+    private static final String HEALTH_CHECK_UNHEALTHY_THRESHOLD = GCEContext.getInstance().getHealthCheckUnhealthyThreshold();\n+    private static final String HEALTH_CHECK_HEALTHY_THRESHOLD = GCEContext.getInstance().getHealthCheckHealthyThreshold();\n+\n+    //a timeout for operation completion\n+    private static final int OPERATION_TIMEOUT = Integer.parseInt(GCEContext.getInstance().getOperationTimeout());\n+    static Compute compute;\n+\n+    /**\n+     * Constructor for GCE Operations Class\n+     */\n+    public GCEOperations() throws IOException, GeneralSecurityException {\n+        buildComputeEngineObject();\n+    }\n+\n+    /**\n+     * Authorize and build compute engine object\n+     */\n+    private void buildComputeEngineObject() throws IOException, GeneralSecurityException {\n+\n+        try {\n+\n+            if (log.isDebugEnabled()) {\n+                log.debug(\"Authorizing and building the compute engine object\");\n+            }\n+\n+            HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();\n+            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();\n+\n+            GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)\n+                    .setJsonFactory(jsonFactory)\n+                    .setServiceAccountId(ACCOUNT_ID)\n+                    .setServiceAccountScopes(Collections.singleton(ComputeScopes.COMPUTE))\n+                    .setServiceAccountPrivateKeyFromP12File(new File(KEY_FILE_PATH))\n+                    .build();\n+\n+            // Create compute engine object\n+            compute = new Compute.Builder(\n+                    httpTransport, jsonFactory, null).setApplicationName(PROJECT_NAME)\n+                    .setHttpRequestInitializer(credential).build();\n+            if (log.isDebugEnabled()) {\n+                log.debug(\"Successfully built the compute engine object\");\n+            }\n+        } catch (GeneralSecurityException e) {\n+            //Security exception occurred. Cant proceed further\n+            log.fatal(\"Could not authenticate and build compute object\");\n+            throw new GeneralSecurityException(e);\n+        } catch (IOException e) {\n+            //IO exception occurred. Cant proceed further\n+            log.fatal(\"Could not authenticate and build compute object\");\n+            throw new IOException(e);\n+        }\n+    }\n+\n+    /**\n+     * Get list of running instances in given project and zone.(This method can be used\n+     * to check whether a given instance is available or not in a given project\n+     * and zone)\n+     *\n+     * @return instanceList - list of instances(members in Stratos side)\n+     */\n+    public static InstanceList getInstanceList(String zoneName, String filter) {\n+        Compute.Instances.List instances;\n+        try {\n+            instances = compute.instances().\n+                    list(PROJECT_ID, zoneName).setFilter(filter);\n+            InstanceList instanceList = instances.execute();\n+            if (instanceList.getItems() == null) {\n+                log.warn(\"No instances found for filter \" + filter + \" and zone \" + zoneName);\n+                return null;\n+            } else {\n+                return instanceList;\n+            }\n+        } catch (IOException e) {\n+            log.warn(\"Could not get instance list from GCE \", e);\n+            return null;\n+        }\n+    }\n+\n+\n+    /**\n+     * Get instance resource URL from given instance name\n+     *\n+     * @param instanceId - Id of the instance provided by IaaS\n+     * @return - Resource URL of the instance in IaaS\n+     */\n+    public static String getInstanceURLFromId(String instanceId) {\n+\n+        String instanceURL;\n+        String zoneName = getZoneNameFromInstanceId(instanceId);\n+        String filter = \"name eq \" + getInstanceNameFromInstanceId(instanceId);\n+        //check whether the given instance is available\n+        InstanceList instanceList = getInstanceList(zoneName, filter);\n+        if (instanceList == null) {\n+            log.warn(\"No matching instance found for filter \" + filter);\n+            return null;\n+        }\n+        for (Instance instance : instanceList.getItems()) {\n+            String instanceIdInIaaS = zoneName + \"/\" + instance.getName();\n+            if (instanceIdInIaaS.equals(instanceId)) {\n+                //instance is available\n+                //getInstance URL\n+                instanceURL = instance.getSelfLink();\n+                return instanceURL;\n+            }\n+        }\n+        log.warn(\"No matching instance found for filter \" + filter);\n+        return null;\n+    }\n+\n+    /**\n+     * Get a given health check resource URL\n+     *\n+     * @param healthCheckName - name of the health check in IaaS\n+     * @return - Resource URL of health check in IaaS side\n+     */\n+    public static String getHealthCheckURLFromName(String healthCheckName) {\n+\n+        String healthCheckURL;\n+\n+        //check whether the given instance is available\n+        HttpHealthCheckList healthCheckList;\n+        healthCheckList = getHealthCheckList();\n+        if (healthCheckList == null) {\n+            log.warn(\"Could not found health check \" + healthCheckName + \" because the health check list is null\");\n+            return null;\n+        }\n+        for (HttpHealthCheck httpHealthCheck : healthCheckList.getItems()) {\n+            if (httpHealthCheck.getName().equals(healthCheckName)) {\n+                //instance is available\n+                //getInstance URL\n+                healthCheckURL = httpHealthCheck.getSelfLink();\n+                return healthCheckURL;\n+            }\n+        }\n+        log.warn(\"Could not found the health check \" + healthCheckName);\n+        return null;\n+    }\n+\n+    /**\n+     * Get list of health checks\n+     *\n+     * @return - list of health checks\n+     */\n+    private static HttpHealthCheckList getHealthCheckList() {\n+\n+        Compute.HttpHealthChecks.List healthChecks;\n+        try {\n+            healthChecks = compute.httpHealthChecks().list(PROJECT_ID);\n+            HttpHealthCheckList healthCheckList = healthChecks.execute();\n+            if (healthCheckList.getItems() == null) {\n+                log.info(\"No health check found for specified project\");\n+                return null;\n+            } else {\n+                return healthCheckList;\n+            }\n+        } catch (IOException e) {\n+            log.warn(\"Could not get health check list from GCE\", e);\n+            return null;\n+        }\n+    }\n+\n+    /**\n+     * Manually create the self link for an instance. This method is useful when the instance is deleted from IaaS\n+     *\n+     * @return - the self link of the instance\n+     */\n+    private static String createInstanceSelfLink(String instanceId) {\n+        return \"https://www.googleapis.com/compute/v1/projects/\" + PROJECT_ID +\n+                \"/zones/\" + getZoneNameFromInstanceId(instanceId) + \"/instances/\" + getInstanceNameFromInstanceId(instanceId);\n+    }\n+\n+    /**\n+     * Creating a new target pool; name should be unique\n+     *\n+     * @param targetPoolName - name of the target pool in IaaS\n+     */\n+    public void createTargetPool(String targetPoolName, String healthCheckName) {\n+\n+        log.info(\"Creating target pool: \" + targetPoolName);\n+        TargetPool targetPool = new TargetPool();\n+        targetPool.setName(targetPoolName);\n+        List<String> httpHealthChecks = new ArrayList<String>();\n+        httpHealthChecks.add(getHealthCheckURLFromName(healthCheckName));\n+        targetPool.setHealthChecks(httpHealthChecks);\n+\n+        try {\n+            Operation operation =\n+                    compute.targetPools().insert(PROJECT_ID, REGION_NAME, targetPool).execute();\n+            waitForRegionOperationCompletion(operation.getName());\n+\n+        } catch (Exception e) {\n+            log.warn(\"Could not create target pool: \" + targetPoolName + \" \" + e);\n+        }\n+        log.info(\"Target pool \" + targetPoolName + \" was created\");\n+    }\n+\n+    /**\n+     * Deleting an exiting target pool in IaaS\n+     *\n+     * @param targetPoolName - Name of the target pool in IaaS\n+     */\n+    public void deleteTargetPool(String targetPoolName) {\n+        log.info(\"Deleting target pool: \" + targetPoolName);\n+        try {\n+            Operation operation = compute.targetPools().delete(PROJECT_ID, REGION_NAME, targetPoolName).execute();\n+            waitForRegionOperationCompletion(operation.getName());\n+\n+        } catch (Exception e) {\n+            log.warn(\"Could not delete target pool \" + targetPoolName + \" \" + e);\n+        }\n+        log.info(\"Target pool: \" + targetPoolName + \" was deleted\");\n+    }\n+\n+    /**\n+     * create forwarding rule by using given target pool and protocol\n+     *\n+     * @param forwardingRuleName - name of the forwarding rule in IaaS to be created\n+     * @param targetPoolName     - name of the target pool in IaaS which is already created\n+     * @param protocol           - The protocol which is used to forward traffic. Should be either TCP or UDP\n+     */\n+\n+    public void createForwardingRule(String forwardingRuleName, String targetPoolName, String protocol,\n+                                     String portRange) {\n+\n+        log.info(\"Creating a forwarding rule: \" + forwardingRuleName);\n+        //Need to get target pool resource URL\n+        TargetPool targetPool = getTargetPool(targetPoolName);\n+        String targetPoolURL = targetPool.getSelfLink();\n+        ForwardingRule forwardingRule = new ForwardingRule();\n+        forwardingRule.setName(forwardingRuleName);\n+        forwardingRule.setTarget(targetPoolURL);\n+        forwardingRule.setIPProtocol(protocol);\n+        forwardingRule.setPortRange(portRange);\n+        try {\n+            Operation operation = compute.forwardingRules().insert(PROJECT_ID, REGION_NAME, forwardingRule).execute();\n+            waitForRegionOperationCompletion(operation.getName());\n+        } catch (Exception e) {\n+            log.warn(\"Could not create a forwarding rule \" + forwardingRuleName + \" \" + e);\n+        }\n+        log.info(\"Forwarding rule: \" + forwardingRuleName + \" was created\");\n+    }\n+\n+    /**\n+     * Deleting a existing forwarding rule in IaaS\n+     *\n+     * @param forwardingRuleName - Forwarding rule name in IaaS\n+     */\n+    public void deleteForwardingRule(String forwardingRuleName) {\n+        log.info(\"Deleting forwarding rule: \" + forwardingRuleName);\n+        try {\n+            Operation operation = compute.forwardingRules().\n+                    delete(PROJECT_ID, REGION_NAME, forwardingRuleName).execute();\n+            waitForRegionOperationCompletion(operation.getName());\n+        } catch (Exception e) {\n+            log.warn(\"Could not delete forwarding rule \" + forwardingRuleName + \" \" + e);\n+        }\n+        log.info(\"Forwarding rule \" + forwardingRuleName + \" was deleted\");\n+    }\n+\n+    /**\n+     * Check whether the given target pool is already exists in the given project and region.\n+     * Target pools are unique for regions, not for zones\n+     *\n+     * @param targetPoolName - target pool name in IaaS\n+     */\n+    public boolean isTargetPoolExists(String targetPoolName) {\n+\n+        try {\n+            Compute.TargetPools.List targetPools = compute.targetPools().\n+                    list(PROJECT_ID, REGION_NAME);\n+            TargetPoolList targetPoolList = targetPools.execute();\n+            for (TargetPool targetPool : targetPoolList.getItems()) {\n+                if (targetPool.getName().equals(targetPoolName)) {\n+                    if (log.isDebugEnabled()) {\n+                        log.debug(\"Target pool \" + targetPoolName + \" exists\");\n+                    }\n+                    return true;\n+                }\n+            }\n+        } catch (IOException e) {\n+            log.warn(\"Could not check whether the target pool \" + targetPoolName + \" exists or not \" + e);\n+        }\n+        if (log.isDebugEnabled()) {\n+            log.debug(\"Target pool \" + targetPoolName + \" does not exist\");\n+        }\n+        return false;\n+    }\n+\n+    /**\n+     * Get a target pool already created in GCE\n+     *\n+     * @param targetPoolName - target pool name in IaaS\n+     * @return - target pool object\n+     */\n+    public TargetPool getTargetPool(String targetPoolName) {\n+\n+        try {\n+            if (isTargetPoolExists(targetPoolName)) {\n+                return compute.targetPools().get(PROJECT_ID, REGION_NAME, targetPoolName).execute();\n+            } else {\n+                if (log.isDebugEnabled()) {\n+                    log.debug(\"Requested Target Pool \" + targetPoolName + \" Is not Available\");\n+                }\n+            }\n+            return null;\n+        } catch (IOException e) {\n+            log.warn(\"Could not get target pool \" + targetPoolName + \" \" + e);\n+        }\n+        return null;\n+    }\n+\n+    /**\n+     * Remove given set of instances from target pool\n+     *\n+     * @param targetPoolName   - target pool name from IaaS\n+     * @param instancesIdsList - List of instances to be removed from target pool\n+     */\n+    public void removeInstancesFromTargetPool(List<String> instancesIdsList, String targetPoolName) {\n+\n+        log.info(\"Removing instances from target pool: \" + targetPoolName);\n+        if (instancesIdsList.isEmpty()) {\n+            log.warn(\"Cannot remove instances to target pool. Because instancesNamesList is empty.\");\n+            return;\n+        }\n+\n+        List<InstanceReference> instanceReferenceList = new ArrayList<InstanceReference>();\n+\n+        //add instance to instance reference list, we should use the instance URL\n+        for (String instanceId : instancesIdsList) { //for all instances\n+            String instanceUrl = createInstanceSelfLink(instanceId);\n+            instanceReferenceList.add(new InstanceReference().\n+                    setInstance(instanceUrl));\n+        }\n+\n+        //create target pools add instance request and set instance to it\n+        TargetPoolsRemoveInstanceRequest targetPoolsRemoveInstanceRequest = new\n+                TargetPoolsRemoveInstanceRequest();\n+        if (instanceReferenceList.isEmpty()) {\n+            log.warn(\"Could not remove instances from target pool \" + targetPoolName + \" because instance reference list is null\");\n+            return;\n+        }\n+        targetPoolsRemoveInstanceRequest.setInstances(instanceReferenceList);\n+\n+        try {\n+            //execute\n+            Operation operation = compute.targetPools().removeInstance(PROJECT_ID, REGION_NAME,\n+                    targetPoolName, targetPoolsRemoveInstanceRequest).execute();\n+            waitForRegionOperationCompletion(operation.getName());\n+\n+        } catch (Exception e) {\n+            log.warn(\"Could not remove instances from target pool \" + targetPoolName + \" \" + e);\n+        }\n+        log.info(\"Instances are removed from target pool: \" + targetPoolName);\n+    }\n+\n+    /**\n+     * Add a given list of instances to a target pool\n+     *\n+     * @param instancesIdsList - list of instance Ids\n+     * @param targetPoolName   - target pool name in IaaS\n+     */\n+    public void addInstancesToTargetPool(List<String> instancesIdsList, String targetPoolName) {\n+\n+        log.info(\"Adding instances to target pool: \" + targetPoolName);\n+\n+        if (instancesIdsList.isEmpty()) {\n+            log.warn(\"Cannot add instances to target pool. InstancesNamesList is empty.\");\n+            return;\n+        }\n+\n+        List<InstanceReference> instanceReferenceList = new ArrayList<InstanceReference>();\n+\n+        //add instance to instance reference list, we should use the instance URL\n+        for (String instanceId : instancesIdsList) { //for all instances\n+\n+            String instanceUrl = getInstanceURLFromId(instanceId);\n+            if (instanceUrl != null) {\n+                instanceReferenceList.add(new InstanceReference().\n+                        setInstance(instanceUrl));\n+            }\n+\n+        }\n+\n+        //create target pools add instance request and set instance to it\n+        TargetPoolsAddInstanceRequest targetPoolsAddInstanceRequest = new\n+                TargetPoolsAddInstanceRequest();\n+        if (instanceReferenceList.isEmpty()) {\n+            log.warn(\"Could not add instances to target pool \" + targetPoolName + \" because instance reference list is null\");\n+            return;\n+        }\n+\n+        targetPoolsAddInstanceRequest.setInstances(instanceReferenceList);\n+\n+        try {\n+            //execute\n+            Operation operation = compute.targetPools().addInstance(PROJECT_ID, REGION_NAME,\n+                    targetPoolName, targetPoolsAddInstanceRequest).execute();\n+            waitForRegionOperationCompletion(operation.getName());\n+\n+        } catch (Exception e) {\n+            log.warn(\"Could not add instance to target pool\" + targetPoolName + \" \" + e);\n+        }\n+        log.info(\"Added instances to target pool: \" + targetPoolName);\n+    }\n+\n+    /**\n+     * Create a health check in IaaS\n+     *\n+     * @param healthCheckName - name of the health check to be created\n+     */\n+    public void createHealthCheck(String healthCheckName) {\n+\n+        log.info(\"Creating health check: \" + healthCheckName);\n+\n+        HttpHealthCheck httpHealthCheck = new HttpHealthCheck();\n+        httpHealthCheck.setName(healthCheckName);\n+        httpHealthCheck.setRequestPath(HEALTH_CHECK_REQUEST_PATH);\n+        httpHealthCheck.setPort(Integer.parseInt(HEALTH_CHECK_PORT));\n+        httpHealthCheck.setTimeoutSec(Integer.parseInt(HEALTH_CHECK_TIME_OUT_SEC));\n+        httpHealthCheck.setCheckIntervalSec(Integer.parseInt(HEALTH_CHECK_INTERVAL_SEC));\n+        httpHealthCheck.setUnhealthyThreshold(Integer.parseInt(HEALTH_CHECK_UNHEALTHY_THRESHOLD));\n+        httpHealthCheck.setHealthyThreshold(Integer.parseInt(HEALTH_CHECK_HEALTHY_THRESHOLD));\n+        try {\n+            Operation operation = compute.httpHealthChecks().insert(PROJECT_ID, httpHealthCheck).execute();\n+            waitForGlobalOperationCompletion(operation.getName());\n+\n+        } catch (Exception e) {\n+            log.error(\"Could not create health check \" + healthCheckName + \" \" + e);\n+        }\n+        log.info(\"Health check \" + healthCheckName + \" was created\");\n+    }\n+\n+    public void deleteHealthCheck(String healthCheckName) {\n+        log.info(\"Deleting Health Check: \" + healthCheckName);\n+        try {\n+            Operation operation = compute.httpHealthChecks().delete(PROJECT_ID, healthCheckName).execute();\n+            waitForGlobalOperationCompletion(operation.getName());\n+\n+        } catch (Exception e) {\n+            log.warn(\"Could not get delete health check \" + healthCheckName + \" \" + e);\n+        }\n+        log.info(\"Health check: \" + healthCheckName + \" was deleted\");","path":"extensions/load-balancer/gce-extension/src/main/java/org/apache/stratos/gce/extension/util/GCEOperations.java","position":503,"original_position":503,"commit_id":"8a426706c8c61db3b9703f2bca1edebb0d20add1","original_commit_id":"8a426706c8c61db3b9703f2bca1edebb0d20add1","user":{"login":"swgkg","id":7394424,"avatar_url":"https://avatars.githubusercontent.com/u/7394424?v=3","gravatar_id":"","url":"https://api.github.com/users/swgkg","html_url":"https://github.com/swgkg","followers_url":"https://api.github.com/users/swgkg/followers","following_url":"https://api.github.com/users/swgkg/following{/other_user}","gists_url":"https://api.github.com/users/swgkg/gists{/gist_id}","starred_url":"https://api.github.com/users/swgkg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swgkg/subscriptions","organizations_url":"https://api.github.com/users/swgkg/orgs","repos_url":"https://api.github.com/users/swgkg/repos","events_url":"https://api.github.com/users/swgkg/events{/privacy}","received_events_url":"https://api.github.com/users/swgkg/received_events","type":"User","site_admin":false},"body":"This log.info message is not relevant.IMO it need to come under the try block.","created_at":"2015-08-11T05:07:34Z","updated_at":"2015-08-11T05:07:34Z","html_url":"https://github.com/apache/stratos/pull/419#discussion_r36712101","pull_request_url":"https://api.github.com/repos/apache/stratos/pulls/419","_links":{"self":{"href":"https://api.github.com/repos/apache/stratos/pulls/comments/36712101"},"html":{"href":"https://github.com/apache/stratos/pull/419#discussion_r36712101"},"pull_request":{"href":"https://api.github.com/repos/apache/stratos/pulls/419"}}},"pull_request":{"url":"https://api.github.com/repos/apache/stratos/pulls/419","id":41868171,"html_url":"https://github.com/apache/stratos/pull/419","diff_url":"https://github.com/apache/stratos/pull/419.diff","patch_url":"https://github.com/apache/stratos/pull/419.patch","issue_url":"https://api.github.com/repos/apache/stratos/issues/419","number":419,"state":"open","locked":false,"title":"Google compute engine load balancing support for stratos","user":{"login":"asankasanjaya","id":8134350,"avatar_url":"https://avatars.githubusercontent.com/u/8134350?v=3","gravatar_id":"","url":"https://api.github.com/users/asankasanjaya","html_url":"https://github.com/asankasanjaya","followers_url":"https://api.github.com/users/asankasanjaya/followers","following_url":"https://api.github.com/users/asankasanjaya/following{/other_user}","gists_url":"https://api.github.com/users/asankasanjaya/gists{/gist_id}","starred_url":"https://api.github.com/users/asankasanjaya/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asankasanjaya/subscriptions","organizations_url":"https://api.github.com/users/asankasanjaya/orgs","repos_url":"https://api.github.com/users/asankasanjaya/repos","events_url":"https://api.github.com/users/asankasanjaya/events{/privacy}","received_events_url":"https://api.github.com/users/asankasanjaya/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-08-07T08:01:43Z","updated_at":"2015-08-11T05:07:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"07186b621c6fb78957db9b472f54ccee744f94a2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/stratos/pulls/419/commits","review_comments_url":"https://api.github.com/repos/apache/stratos/pulls/419/comments","review_comment_url":"https://api.github.com/repos/apache/stratos/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/stratos/issues/419/comments","statuses_url":"https://api.github.com/repos/apache/stratos/statuses/8a426706c8c61db3b9703f2bca1edebb0d20add1","head":{"label":"asankasanjaya:master","ref":"master","sha":"8a426706c8c61db3b9703f2bca1edebb0d20add1","user":{"login":"asankasanjaya","id":8134350,"avatar_url":"https://avatars.githubusercontent.com/u/8134350?v=3","gravatar_id":"","url":"https://api.github.com/users/asankasanjaya","html_url":"https://github.com/asankasanjaya","followers_url":"https://api.github.com/users/asankasanjaya/followers","following_url":"https://api.github.com/users/asankasanjaya/following{/other_user}","gists_url":"https://api.github.com/users/asankasanjaya/gists{/gist_id}","starred_url":"https://api.github.com/users/asankasanjaya/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asankasanjaya/subscriptions","organizations_url":"https://api.github.com/users/asankasanjaya/orgs","repos_url":"https://api.github.com/users/asankasanjaya/repos","events_url":"https://api.github.com/users/asankasanjaya/events{/privacy}","received_events_url":"https://api.github.com/users/asankasanjaya/received_events","type":"User","site_admin":false},"repo":{"id":36859091,"name":"stratos","full_name":"asankasanjaya/stratos","owner":{"login":"asankasanjaya","id":8134350,"avatar_url":"https://avatars.githubusercontent.com/u/8134350?v=3","gravatar_id":"","url":"https://api.github.com/users/asankasanjaya","html_url":"https://github.com/asankasanjaya","followers_url":"https://api.github.com/users/asankasanjaya/followers","following_url":"https://api.github.com/users/asankasanjaya/following{/other_user}","gists_url":"https://api.github.com/users/asankasanjaya/gists{/gist_id}","starred_url":"https://api.github.com/users/asankasanjaya/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asankasanjaya/subscriptions","organizations_url":"https://api.github.com/users/asankasanjaya/orgs","repos_url":"https://api.github.com/users/asankasanjaya/repos","events_url":"https://api.github.com/users/asankasanjaya/events{/privacy}","received_events_url":"https://api.github.com/users/asankasanjaya/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/asankasanjaya/stratos","description":"Mirror of Apache Stratos","fork":true,"url":"https://api.github.com/repos/asankasanjaya/stratos","forks_url":"https://api.github.com/repos/asankasanjaya/stratos/forks","keys_url":"https://api.github.com/repos/asankasanjaya/stratos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/asankasanjaya/stratos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/asankasanjaya/stratos/teams","hooks_url":"https://api.github.com/repos/asankasanjaya/stratos/hooks","issue_events_url":"https://api.github.com/repos/asankasanjaya/stratos/issues/events{/number}","events_url":"https://api.github.com/repos/asankasanjaya/stratos/events","assignees_url":"https://api.github.com/repos/asankasanjaya/stratos/assignees{/user}","branches_url":"https://api.github.com/repos/asankasanjaya/stratos/branches{/branch}","tags_url":"https://api.github.com/repos/asankasanjaya/stratos/tags","blobs_url":"https://api.github.com/repos/asankasanjaya/stratos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/asankasanjaya/stratos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/asankasanjaya/stratos/git/refs{/sha}","trees_url":"https://api.github.com/repos/asankasanjaya/stratos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/asankasanjaya/stratos/statuses/{sha}","languages_url":"https://api.github.com/repos/asankasanjaya/stratos/languages","stargazers_url":"https://api.github.com/repos/asankasanjaya/stratos/stargazers","contributors_url":"https://api.github.com/repos/asankasanjaya/stratos/contributors","subscribers_url":"https://api.github.com/repos/asankasanjaya/stratos/subscribers","subscription_url":"https://api.github.com/repos/asankasanjaya/stratos/subscription","commits_url":"https://api.github.com/repos/asankasanjaya/stratos/commits{/sha}","git_commits_url":"https://api.github.com/repos/asankasanjaya/stratos/git/commits{/sha}","comments_url":"https://api.github.com/repos/asankasanjaya/stratos/comments{/number}","issue_comment_url":"https://api.github.com/repos/asankasanjaya/stratos/issues/comments{/number}","contents_url":"https://api.github.com/repos/asankasanjaya/stratos/contents/{+path}","compare_url":"https://api.github.com/repos/asankasanjaya/stratos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/asankasanjaya/stratos/merges","archive_url":"https://api.github.com/repos/asankasanjaya/stratos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/asankasanjaya/stratos/downloads","issues_url":"https://api.github.com/repos/asankasanjaya/stratos/issues{/number}","pulls_url":"https://api.github.com/repos/asankasanjaya/stratos/pulls{/number}","milestones_url":"https://api.github.com/repos/asankasanjaya/stratos/milestones{/number}","notifications_url":"https://api.github.com/repos/asankasanjaya/stratos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/asankasanjaya/stratos/labels{/name}","releases_url":"https://api.github.com/repos/asankasanjaya/stratos/releases{/id}","created_at":"2015-06-04T08:50:34Z","updated_at":"2015-06-04T08:50:41Z","pushed_at":"2015-08-08T14:06:08Z","git_url":"git://github.com/asankasanjaya/stratos.git","ssh_url":"git@github.com:asankasanjaya/stratos.git","clone_url":"https://github.com/asankasanjaya/stratos.git","svn_url":"https://github.com/asankasanjaya/stratos","homepage":null,"size":60160,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"3eb7d7c25cef217c80dfce97de61646359f9711e","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":20432793,"name":"stratos","full_name":"apache/stratos","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/stratos","description":"Mirror of Apache Stratos","fork":false,"url":"https://api.github.com/repos/apache/stratos","forks_url":"https://api.github.com/repos/apache/stratos/forks","keys_url":"https://api.github.com/repos/apache/stratos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/stratos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/stratos/teams","hooks_url":"https://api.github.com/repos/apache/stratos/hooks","issue_events_url":"https://api.github.com/repos/apache/stratos/issues/events{/number}","events_url":"https://api.github.com/repos/apache/stratos/events","assignees_url":"https://api.github.com/repos/apache/stratos/assignees{/user}","branches_url":"https://api.github.com/repos/apache/stratos/branches{/branch}","tags_url":"https://api.github.com/repos/apache/stratos/tags","blobs_url":"https://api.github.com/repos/apache/stratos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/stratos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/stratos/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/stratos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/stratos/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/stratos/languages","stargazers_url":"https://api.github.com/repos/apache/stratos/stargazers","contributors_url":"https://api.github.com/repos/apache/stratos/contributors","subscribers_url":"https://api.github.com/repos/apache/stratos/subscribers","subscription_url":"https://api.github.com/repos/apache/stratos/subscription","commits_url":"https://api.github.com/repos/apache/stratos/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/stratos/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/stratos/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/stratos/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/stratos/contents/{+path}","compare_url":"https://api.github.com/repos/apache/stratos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/stratos/merges","archive_url":"https://api.github.com/repos/apache/stratos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/stratos/downloads","issues_url":"https://api.github.com/repos/apache/stratos/issues{/number}","pulls_url":"https://api.github.com/repos/apache/stratos/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/stratos/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/stratos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/stratos/labels{/name}","releases_url":"https://api.github.com/repos/apache/stratos/releases{/id}","created_at":"2014-06-03T07:00:07Z","updated_at":"2015-08-09T09:27:45Z","pushed_at":"2015-08-11T04:29:35Z","git_url":"git://github.com/apache/stratos.git","ssh_url":"git@github.com:apache/stratos.git","clone_url":"https://github.com/apache/stratos.git","svn_url":"https://github.com/apache/stratos","homepage":null,"size":111663,"stargazers_count":89,"watchers_count":89,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":78,"mirror_url":"git://git.apache.org/stratos.git","open_issues_count":7,"forks":78,"open_issues":7,"watchers":89,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/stratos/pulls/419"},"html":{"href":"https://github.com/apache/stratos/pull/419"},"issue":{"href":"https://api.github.com/repos/apache/stratos/issues/419"},"comments":{"href":"https://api.github.com/repos/apache/stratos/issues/419/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/stratos/pulls/419/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/stratos/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/stratos/pulls/419/commits"},"statuses":{"href":"https://api.github.com/repos/apache/stratos/statuses/8a426706c8c61db3b9703f2bca1edebb0d20add1"}}}}