Merge branch 'master' into 'master'

Implement multi-tenant api publishing

See merge request entgra/carbon-device-mgt!900
feature/traccar-sync
Pahansith Gunathilake 2 years ago
commit cd6a4e3c0c

@ -149,8 +149,8 @@
org.wso2.carbon.apimgt.webapp.publisher.* org.wso2.carbon.apimgt.webapp.publisher.*
</Export-Package> </Export-Package>
<Import-Package> <Import-Package>
com.google.gson;version="2.3", com.google.gson;version="[2.3,2.8.6)",
com.google.gson.reflect;version="2.3", com.google.gson.reflect;version="[2.3,2.8.6)",
io.swagger.annotations, io.swagger.annotations,
javax.servlet;version="2.6", javax.servlet;version="2.6",
javax.xml, javax.xml,
@ -169,6 +169,7 @@
org.wso2.carbon.apimgt.api, org.wso2.carbon.apimgt.api,
org.wso2.carbon.apimgt.api.model, org.wso2.carbon.apimgt.api.model,
org.wso2.carbon.apimgt.impl, org.wso2.carbon.apimgt.impl,
org.wso2.carbon.apimgt.impl.utils,
org.wso2.carbon.apimgt.webapp.publisher, org.wso2.carbon.apimgt.webapp.publisher,
org.wso2.carbon.apimgt.webapp.publisher.config, org.wso2.carbon.apimgt.webapp.publisher.config,
org.wso2.carbon.apimgt.webapp.publisher.dto, org.wso2.carbon.apimgt.webapp.publisher.dto,

@ -18,6 +18,9 @@
*/ */
package org.wso2.carbon.apimgt.webapp.publisher; package org.wso2.carbon.apimgt.webapp.publisher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope; import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope;
import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiUriTemplate; import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiUriTemplate;
import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIManagementException;
@ -36,10 +39,15 @@ import org.wso2.carbon.apimgt.impl.APIManagerFactory;
import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig; import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig;
import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException; import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.tenant.TenantSearchResult;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -55,17 +63,54 @@ public class APIPublisherServiceImpl implements APIPublisherService {
private static final String CREATED_STATUS = "CREATED"; private static final String CREATED_STATUS = "CREATED";
private static final String PUBLISH_ACTION = "Publish"; private static final String PUBLISH_ACTION = "Publish";
public static final APIManagerFactory API_MANAGER_FACTORY = APIManagerFactory.getInstance(); public static final APIManagerFactory API_MANAGER_FACTORY = APIManagerFactory.getInstance();
private static final Log log = LogFactory.getLog(APIPublisherServiceImpl.class);
@Override @Override
public void publishAPI(APIConfig apiConfig) throws APIManagerPublisherException { public void publishAPI(APIConfig apiConfig) throws APIManagerPublisherException {
String tenantDomain = MultitenantUtils.getTenantDomain(apiConfig.getOwner()); WebappPublisherConfig config = WebappPublisherConfig.getInstance();
List<String> tenants = new ArrayList<>(Collections.singletonList(APIConstants.SUPER_TENANT_DOMAIN));
tenants.addAll(config.getTenants().getTenant());
RealmService realmService = (RealmService) PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getOSGiService(RealmService.class, null);
try {
boolean tenantFound = false;
boolean tenantsLoaded = false;
TenantSearchResult tenantSearchResult = null;
for (String tenantDomain : tenants) {
PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
if (!tenantsLoaded) {
tenantSearchResult = realmService.getTenantManager()
.listTenants(Integer.MAX_VALUE, 0, "asc", "UM_ID", null);
tenantsLoaded = true;
}
if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
tenantFound = true;
realmService.getTenantUserRealm(MultitenantConstants.SUPER_TENANT_ID)
.getRealmConfiguration().getAdminUserName();
} else {
List<Tenant> allTenants = tenantSearchResult.getTenantList();
for (Tenant tenant : allTenants) {
if (tenant.getDomain().equals(tenantDomain)) {
tenantFound = true;
tenant.getAdminName();
break;
} else {
tenantFound = false;
}
}
}
if (tenantFound) {
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(apiConfig.getOwner()); PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(apiConfig.getOwner());
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try { try {
apiConfig.setOwner(APIUtil.getTenantAdminUserName(tenantDomain));
apiConfig.setTenantDomain(tenantDomain);
APIProvider apiProvider = API_MANAGER_FACTORY.getAPIProvider(apiConfig.getOwner()); APIProvider apiProvider = API_MANAGER_FACTORY.getAPIProvider(apiConfig.getOwner());
APIIdentifier apiIdentifier = new APIIdentifier(apiConfig.getOwner(), apiConfig.getName(), apiConfig.getVersion()); APIIdentifier apiIdentifier = new APIIdentifier(APIUtil.replaceEmailDomain(apiConfig.getOwner()),
apiConfig.getName(), apiConfig.getVersion());
if (!apiProvider.isAPIAvailable(apiIdentifier)) { if (!apiProvider.isAPIAvailable(apiIdentifier)) {
@ -82,6 +127,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
} }
} }
API api = getAPI(apiConfig, true); API api = getAPI(apiConfig, true);
api.setId(apiIdentifier);
API createdAPI = apiProvider.addAPI(api); API createdAPI = apiProvider.addAPI(api);
if (CREATED_STATUS.equals(createdAPI.getStatus())) { if (CREATED_STATUS.equals(createdAPI.getStatus())) {
apiProvider.changeLifeCycleStatus(tenantDomain, createdAPI.getUuid(), PUBLISH_ACTION, null); apiProvider.changeLifeCycleStatus(tenantDomain, createdAPI.getUuid(), PUBLISH_ACTION, null);
@ -98,7 +144,6 @@ public class APIPublisherServiceImpl implements APIPublisherService {
List<APIRevisionDeployment> apiRevisionDeploymentList = new ArrayList<>(); List<APIRevisionDeployment> apiRevisionDeploymentList = new ArrayList<>();
apiRevisionDeploymentList.add(apiRevisionDeployment); apiRevisionDeploymentList.add(apiRevisionDeployment);
apiProvider.deployAPIRevision(createdAPI.getUuid(), apiRevisionId, apiRevisionDeploymentList); apiProvider.deployAPIRevision(createdAPI.getUuid(), apiRevisionId, apiRevisionDeploymentList);
} }
} else { } else {
if (WebappPublisherConfig.getInstance().isEnabledUpdateApi()) { if (WebappPublisherConfig.getInstance().isEnabledUpdateApi()) {
@ -189,14 +234,21 @@ public class APIPublisherServiceImpl implements APIPublisherService {
} }
} }
} }
} catch (FaultGatewaysException | APIManagementException e) { } catch (FaultGatewaysException | APIManagementException e) {
String msg = "Error occurred while publishing api";
log.error(msg, e);
throw new APIManagerPublisherException(e); throw new APIManagerPublisherException(e);
} finally { } finally {
PrivilegedCarbonContext.endTenantFlow(); PrivilegedCarbonContext.endTenantFlow();
} }
} }
}
} catch (UserStoreException e) {
String msg = "Error occurred while retrieving admin user from tenant user realm";
log.error(msg, e);
throw new APIManagerPublisherException(e);
}
}
private API getAPI(APIConfig config, boolean includeScopes) { private API getAPI(APIConfig config, boolean includeScopes) {

@ -0,0 +1,45 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.wso2.carbon.apimgt.webapp.publisher.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Tenants", propOrder = {
"tenant"
})
public class Tenants {
@XmlElement(name = "Tenant")
protected List<String> tenant = new ArrayList<>();;
/**
* Gets the value of the profile property.
*
*/
public List<String> getTenant() {
return this.tenant;
}
}

@ -43,6 +43,7 @@ public class WebappPublisherConfig {
private boolean isEnabledUpdateApi; private boolean isEnabledUpdateApi;
private Profiles profiles; private Profiles profiles;
private static boolean isInitialized = false; private static boolean isInitialized = false;
private Tenants tenants;
private static WebappPublisherConfig config; private static WebappPublisherConfig config;
@ -100,6 +101,15 @@ public class WebappPublisherConfig {
this.profiles = profiles; this.profiles = profiles;
} }
@XmlElement(name = "Tenants", required = true)
public Tenants getTenants() {
return tenants;
}
public void setTenants(Tenants tenants) {
this.tenants = tenants;
}
public synchronized static void init() throws WebappPublisherConfigurationFailedException { public synchronized static void init() throws WebappPublisherConfigurationFailedException {
if (isInitialized) { if (isInitialized) {
return; return;

@ -36,4 +36,9 @@
<Profiles> <Profiles>
<Profile>default</Profile> <Profile>default</Profile>
</Profiles> </Profiles>
<!-- Apart from the super tenant, APIs will be published to the following tenants -->
<Tenants>
<!-- <Tenant>example.com</Tenant> -->
</Tenants>
</WebappPublisherConfigs> </WebappPublisherConfigs>

@ -53,4 +53,13 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</Profiles> </Profiles>
<!-- Apart from the super tenant, APIs will be published to the following tenants -->
<Tenants>
{% if webapp_publisher_configs.tenants is defined %}
{%- for tenant in webapp_publisher_configs.tenants -%}
<Tenant>{{tenant}}</Tenant>
{% endfor %}
{% endif %}
</Tenants>
</WebappPublisherConfigs> </WebappPublisherConfigs>
Loading…
Cancel
Save