package org.gcube.gcat.configuration; import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.WebApplicationException; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.common.encryption.encrypter.StringEncrypter; import org.gcube.common.resources.gcore.GenericResource; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; import org.gcube.common.resources.gcore.ServiceEndpoint.Profile; import org.gcube.common.resources.gcore.ServiceEndpoint.Property; import org.gcube.common.resources.gcore.ServiceEndpoint.Runtime; import org.gcube.common.resources.gcore.common.Platform; import org.gcube.common.resources.gcore.utils.Group; import org.gcube.gcat.api.configuration.CKANDB; import org.gcube.gcat.api.configuration.CatalogueConfiguration; import org.gcube.informationsystem.publisher.RegistryPublisher; import org.gcube.informationsystem.publisher.RegistryPublisherFactory; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.gcube.resources.discovery.icclient.ICFactory; import org.gcube.smartgears.ContextProvider; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ public class GCoreISConfigurationProxy { private static final Logger logger = LoggerFactory.getLogger(GCoreISConfigurationProxy.class); // property to retrieve the master service endpoint into the /root scope public final static String IS_ROOT_MASTER_PROPERTY_KEY = "IS_ROOT_MASTER"; // true, false.. missing means false as public final static String DEFAULT_ORGANIZATION_PROPERTY_KEY = "DEFAULT_ORGANIZATION"; public final static String SUPPORTED_ORGANIZATION_PROPERTY_KEY = "SUPPORTED_ORGANIZATION"; public final static String API_KEY_PROPERTY_KEY = "API_KEY"; public final static String SOLR_INDEX_ADDRESS_PROPERTY_KEY = "SOLR_INDEX_ADDRESS"; public final static String SOCIAL_POST_PROPERTY_KEY = "SOCIAL_POST"; public final static String ALERT_USERS_ON_POST_CREATION_PROPERTY_KEY = "ALERT_USERS_ON_POST_CREATION"; public final static String MODERATION_ENABLED_KEY_PROPERTY_KEY = "MODERATION_ENABLED"; public final static String CKAN_DB_URL_PROPERTY_KEY = "CKAN_DB_URL"; public final static String CKAN_DB_USERNAME_PROPERTY_KEY = "CKAN_DB_USERNAME"; public final static String CKAN_DB_PASSWORD_PROPERTY_KEY = "CKAN_DB_PASSWORD"; // CKAN Instance info private final static String CATEGORY = "Application"; private final static String NAME = "CKanDataCatalogue"; protected final String context; protected CatalogueConfiguration catalogueConfiguration; public GCoreISConfigurationProxy(String context) { this.context = context; } public GCoreISConfigurationProxy(String context, CatalogueConfiguration catalogueConfiguration) { this(context); this.catalogueConfiguration = catalogueConfiguration; } public CatalogueConfiguration getCatalogueConfiguration() { if (catalogueConfiguration == null) { getCatalogueConfigurationFromIS(); } return catalogueConfiguration; } protected AccessPoint getAccessPoint(Profile profile) { Group accessPoints = profile.accessPoints(); Iterator accessPointIterator = accessPoints.iterator(); AccessPoint accessPoint = accessPointIterator.next(); return accessPoint; } protected String getDefaultSolrURL(String ckanURL) { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(ckanURL); stringBuffer.append(ckanURL.endsWith("/")?"":"/"); stringBuffer.append("solr/"); return stringBuffer.toString(); } protected CatalogueConfiguration getCatalogueConfigurationFromIS() { try { boolean mustBeUpdated = false; catalogueConfiguration = new CatalogueConfiguration(context); ServiceEndpoint serviceEndpoint = getServiceEndpoint(); if (serviceEndpoint == null) { throw new InternalServerErrorException("No CKAN configuration on IS"); } catalogueConfiguration.setID(serviceEndpoint.id()); Profile profile = serviceEndpoint.profile(); AccessPoint accessPoint = getAccessPoint(profile); // add this host String ckanURL = accessPoint.address(); catalogueConfiguration.setCkanURL(ckanURL); Map propertyMap = accessPoint.propertyMap(); // retrieve sys admin token String encryptedSysAdminToken = propertyMap.get(API_KEY_PROPERTY_KEY).value(); catalogueConfiguration.setSysAdminToken(StringEncrypter.getEncrypter().decrypt(encryptedSysAdminToken)); String defaultOrganization = null; if (propertyMap.containsKey(DEFAULT_ORGANIZATION_PROPERTY_KEY)) { String org = propertyMap.get(DEFAULT_ORGANIZATION_PROPERTY_KEY).value().trim(); if(org!=null && org.compareTo("")==0) { mustBeUpdated = true; }else { defaultOrganization = org; } }else { mustBeUpdated = true; } catalogueConfiguration.setDefaultOrganization(defaultOrganization); String solrURL = null; if (propertyMap.containsKey(SOLR_INDEX_ADDRESS_PROPERTY_KEY)) { solrURL = propertyMap.get(SOLR_INDEX_ADDRESS_PROPERTY_KEY).value(); }else { solrURL = getDefaultSolrURL(ckanURL); } catalogueConfiguration.setSolrURL(solrURL); // retrieve option to check if the social post has to be made Boolean socialPostEnabled = true; if (propertyMap.containsKey(SOCIAL_POST_PROPERTY_KEY)) { if (propertyMap.get(SOCIAL_POST_PROPERTY_KEY).value().trim().equalsIgnoreCase("false")) { socialPostEnabled = false; } }else { mustBeUpdated = true; } catalogueConfiguration.setSocialPostEnabled(socialPostEnabled); // retrieve option for user alert boolean notificationToUsersEnabled = false; // default is false if (propertyMap.containsKey(ALERT_USERS_ON_POST_CREATION_PROPERTY_KEY)) { if (propertyMap.get(ALERT_USERS_ON_POST_CREATION_PROPERTY_KEY).value().trim() .equalsIgnoreCase("true")) { notificationToUsersEnabled = true; } }else { mustBeUpdated = true; } catalogueConfiguration.setNotificationToUsersEnabled(notificationToUsersEnabled); boolean moderationEnabled = false; // default is false if (propertyMap.containsKey(MODERATION_ENABLED_KEY_PROPERTY_KEY)) { if (propertyMap.get(MODERATION_ENABLED_KEY_PROPERTY_KEY).value().trim().equalsIgnoreCase("true")) { moderationEnabled = true; } }else { mustBeUpdated = true; } catalogueConfiguration.setModerationEnabled(moderationEnabled); Set supportedOrganizations = null; if (propertyMap.containsKey(SUPPORTED_ORGANIZATION_PROPERTY_KEY)) { String jsonArray = propertyMap.get(SUPPORTED_ORGANIZATION_PROPERTY_KEY).value(); supportedOrganizations = unmarshallSupportedOrganizations(jsonArray); removeAllGenericResources(); }else { supportedOrganizations = getSupportedOrganizationsFromGenericResource(); mustBeUpdated = true; } if (supportedOrganizations != null) { catalogueConfiguration.setSupportedOrganizations(supportedOrganizations); if(defaultOrganization==null) { defaultOrganization = supportedOrganizations.toArray(new String[supportedOrganizations.size()])[0]; catalogueConfiguration.setDefaultOrganization(defaultOrganization); } } CKANDB ckanDB = null; if (propertyMap.containsKey(CKAN_DB_URL_PROPERTY_KEY)) { String ckanDBURL = propertyMap.get(CKAN_DB_URL_PROPERTY_KEY).value().trim(); ckanDB = new CKANDB(); ckanDB.setUrl(ckanDBURL); String ckanDBUsername = propertyMap.get(CKAN_DB_USERNAME_PROPERTY_KEY).value().trim(); ckanDB.setUsername(ckanDBUsername); // Password is encrypted String ckanDBPassword = propertyMap.get(CKAN_DB_PASSWORD_PROPERTY_KEY).value().trim(); ckanDB.setPassword(StringEncrypter.getEncrypter().decrypt(ckanDBPassword)); }else { mustBeUpdated = true; ckanDB = getCKANDBFromIS(); } catalogueConfiguration.setCkanDB(ckanDB); if(mustBeUpdated) { logger.warn("The ServiceEndpoint with ID {} in context {} should be updated", serviceEndpoint.id(), context); } } catch (WebApplicationException e) { throw e; } catch (Exception e) { throw new InternalServerErrorException("Error while getting configuration on IS", e); } return catalogueConfiguration; } /** * Retrieve endpoints information from IS for DataCatalogue URL * * @return list of endpoints for ckan data catalogue * @throws Exception */ private List getServiceEndpoints() { SimpleQuery query = queryFor(ServiceEndpoint.class); query.addCondition("$resource/Profile/Category/text() eq '" + CATEGORY + "'"); query.addCondition("$resource/Profile/Name/text() eq '" + NAME + "'"); DiscoveryClient client = clientFor(ServiceEndpoint.class); List serviceEndpoints = client.submit(query); return serviceEndpoints; } private ServiceEndpoint getServiceEndpoint() { List serviceEndpoints = getServiceEndpoints(); if (serviceEndpoints.size() == 0) { logger.error("There is no {} having Category {} and Name {} in this context.", ServiceEndpoint.class.getSimpleName(), CATEGORY, NAME); return null; } ServiceEndpoint serviceEndpoint = null; if (serviceEndpoints.size() > 1) { logger.info("Too many {} having Category {} and Name {} in this context. Looking for the one that has the property {}", ServiceEndpoint.class.getSimpleName(), CATEGORY, NAME, IS_ROOT_MASTER_PROPERTY_KEY); for (ServiceEndpoint se : serviceEndpoints) { Iterator accessPointIterator = se.profile().accessPoints().iterator(); while (accessPointIterator.hasNext()) { ServiceEndpoint.AccessPoint accessPoint = accessPointIterator.next(); // get the is master property Property entry = accessPoint.propertyMap().get(IS_ROOT_MASTER_PROPERTY_KEY); String isMaster = entry != null ? entry.value() : null; if (isMaster == null || !isMaster.equals("true")) { continue; } // set this variable serviceEndpoint = se; return serviceEndpoint; } } // if none of them was master, throw an exception if (serviceEndpoint == null) { throw new InternalServerErrorException( "Too many catalogue configuration on IS and no one with MASTER property"); } } else { serviceEndpoint = serviceEndpoints.get(0); } return serviceEndpoint; } // CKAN Instance info private final static String CKAN_DB_SERVICE_ENDPOINT_CATEGORY= "Database"; private final static String CKAN_DB_SERVICE_ENDPOINT_NAME = "CKanDatabase"; /** * Retrieve endpoints information from IS for DataCatalogue URL * @return list of endpoints for ckan data catalogue * @throws Exception */ protected List getCKANDBServiceEndpoints() { SimpleQuery query = queryFor(ServiceEndpoint.class); query.addCondition("$resource/Profile/Category/text() eq '" + CKAN_DB_SERVICE_ENDPOINT_CATEGORY + "'"); query.addCondition("$resource/Profile/Name/text() eq '" + CKAN_DB_SERVICE_ENDPOINT_NAME + "'"); DiscoveryClient client = clientFor(ServiceEndpoint.class); List serviceEndpoints = client.submit(query); if(serviceEndpoints.size() == 0) { logger.error("There is no {} having category {} and name {} in this context.", ServiceEndpoint.class.getSimpleName(), CKAN_DB_SERVICE_ENDPOINT_CATEGORY, CKAN_DB_SERVICE_ENDPOINT_NAME); throw new InternalServerErrorException("No CKAN configuration on IS"); } return serviceEndpoints; } protected CKANDB getCKANDBFromIS() { try { List serviceEndpoints = getCKANDBServiceEndpoints(); ServiceEndpoint serviceEndpoint = null; if(serviceEndpoints.size() > 1) { logger.info("Too many {} having category {} and name {} in this context. Looking for the one that has the property {}", ServiceEndpoint.class.getSimpleName(), CKAN_DB_SERVICE_ENDPOINT_CATEGORY, CKAN_DB_SERVICE_ENDPOINT_NAME); for(ServiceEndpoint se : serviceEndpoints) { Iterator accessPointIterator = se.profile().accessPoints().iterator(); while(accessPointIterator.hasNext()) { ServiceEndpoint.AccessPoint accessPoint = accessPointIterator.next(); // get the is master property Property entry = accessPoint.propertyMap().get(IS_ROOT_MASTER_PROPERTY_KEY); String isMaster = entry != null ? entry.value() : null; if(isMaster == null || !isMaster.equals("true")) { continue; } // set this variable serviceEndpoint = se; break; } } // if none of them was master, throw an exception if(serviceEndpoint == null) { throw new InternalServerErrorException( "Too many CKAN configuration on IS and no one with MASTER property"); } } else { serviceEndpoint = serviceEndpoints.get(0); } Iterator accessPointIterator = serviceEndpoint.profile().accessPoints().iterator(); while(accessPointIterator.hasNext()) { AccessPoint accessPoint = accessPointIterator.next(); String host = accessPoint.address(); String db = accessPoint.name(); CKANDB ckanDB = new CKANDB(); String url = String.format("jdbc:postgresql://%s/%s", host, db); ckanDB.setUrl(url); ckanDB.setUsername(accessPoint.username()); ckanDB.setPassword(StringEncrypter.getEncrypter().decrypt(accessPoint.password())); return ckanDB; } return null; } catch(WebApplicationException e) { throw e; } catch(Exception e) { throw new InternalServerErrorException("Error while getting configuration on IS", e); } } public static final String GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS = "ApplicationProfile"; public static final String GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS = "Supported CKAN Organizations"; public static final String GENERIC_RESOURCE_CKAN_ORGANIZATIONS = "CKANOrganizations"; private List getGenericResources() { SimpleQuery query = ICFactory.queryFor(GenericResource.class); query.addCondition(String.format("$resource/Profile/SecondaryType/text() eq '%s'", GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS)); query.addCondition( String.format("$resource/Profile/Name/text() eq '%s'", GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS)); DiscoveryClient client = ICFactory.clientFor(GenericResource.class); List genericResources = client.submit(query); return genericResources; } protected String marshallSupportedOrganizations() throws JsonProcessingException { Set supportedOrganizations = catalogueConfiguration.getSupportedOrganizations(); return marshallSupportedOrganizations(supportedOrganizations); } protected String marshallSupportedOrganizations(Set supportedOrganizations) throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper(); ArrayNode arrayNode = objectMapper.createArrayNode(); for(String org : supportedOrganizations) { arrayNode.add(org); } return objectMapper.writeValueAsString(arrayNode); } protected Set unmarshallSupportedOrganizations(String supportedOrganizationsJsonArray){ try { ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(supportedOrganizationsJsonArray); ArrayNode array = (ArrayNode) jsonNode.get(GENERIC_RESOURCE_CKAN_ORGANIZATIONS); Set supportedOrganizations = new HashSet<>(array.size()); for (int i = 0; i < array.size(); i++) { String o = array.get(i).asText(); supportedOrganizations.add(o); } logger.debug("Supported CKAN Organization for current Context ({}) are {}", context, supportedOrganizations); return supportedOrganizations; } catch (Exception e) { return null; } } protected void removeAllGenericResources() { List genericResources = getGenericResources(); removeAllGenericResources(genericResources); } protected void removeAllGenericResources(List genericResources) { RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); for(GenericResource genericResource : genericResources) { registryPublisher.remove(genericResource); } } protected Set getSupportedOrganizationsFromGenericResource() { List genericResources = getGenericResources(); if (genericResources == null || genericResources.size() == 0) { logger.trace( "{} with SecondaryType {} and Name %s not found. Item will be only be created in {} CKAN organization", GenericResource.class.getSimpleName(), GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS, GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS, CatalogueConfiguration.getOrganizationName(context)); return null; } GenericResource genericResource = genericResources.get(0); String supportedOrganizationsJsonArray = genericResource.profile().body().getTextContent(); Set supportedOrganizatins = unmarshallSupportedOrganizations(supportedOrganizationsJsonArray); removeAllGenericResources(genericResources); return supportedOrganizatins; } public void delete() { RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); ServiceEndpoint serviceEndpoint = getServiceEndpoint(); if(serviceEndpoint!=null) { registryPublisher.remove(serviceEndpoint); } List genericResources = getGenericResources(); if(genericResources!=null) { for(GenericResource genericResource : genericResources) { registryPublisher.remove(genericResource); } } } protected Property addProperty(Group properties, String name, String value) { return addProperty(properties, name, value, false); } protected Property addProperty(Group properties, String name, String value, boolean encrypted) { Property property = new Property(); property.nameAndValue(name, value); property.encrypted(encrypted); properties.add(property); return property; } protected Group setAccessPointProperties(AccessPoint accessPoint, boolean update) throws JsonProcessingException { accessPoint.description(String.format("Access Point %s by gcat %s", update ? "updated" : "created", getGcatVersion().toString())); accessPoint.address(catalogueConfiguration.getCkanURL()); // TODO Change ASAP //accessPoint.name("gcat Configuration"); accessPoint.name("CKan Data Catalogue"); Group properties = accessPoint.properties(); addProperty(properties, SOLR_INDEX_ADDRESS_PROPERTY_KEY, catalogueConfiguration.getSolrURL()); addProperty(properties, DEFAULT_ORGANIZATION_PROPERTY_KEY, catalogueConfiguration.getDefaultOrganization()); addProperty(properties, API_KEY_PROPERTY_KEY, catalogueConfiguration.getSysAdminToken(), true); addProperty(properties, SOCIAL_POST_PROPERTY_KEY, Boolean.toString(catalogueConfiguration.isSocialPostEnabled())); addProperty(properties, ALERT_USERS_ON_POST_CREATION_PROPERTY_KEY, Boolean.toString(catalogueConfiguration.isNotificationToUsersEnabled())); addProperty(properties, MODERATION_ENABLED_KEY_PROPERTY_KEY, Boolean.toString(catalogueConfiguration.isModerationEnabled())); addProperty(properties, SUPPORTED_ORGANIZATION_PROPERTY_KEY, marshallSupportedOrganizations()); return properties; } private final static String PLATFORM_NAME = "Tomcat"; protected Version getGcatVersion() { ApplicationContext applicationContext = ContextProvider.get(); ApplicationConfiguration applicationConfiguration = applicationContext.configuration(); Version version = new Version(applicationConfiguration.version()); return version; } /** * Set the version of gcat so that in future implementation * we can understand if the configuration must be updated. * @param platform * @return */ protected Platform setVersion(Platform platform) { Version version = getGcatVersion(); platform.version((short) version.getMajor()); platform.minorVersion((short) version.getMinor()); platform.revisionVersion((short) version.getRevision()); platform.buildVersion((short) 0); return platform; } protected Platform setPlatformProperty(Platform platform) { /* * * Tomcat * * The version of gcat * 2 * 2 * 0 * 0 * */ // TODO change to gcat ASAP // platform.name("gcat"); platform.name(PLATFORM_NAME); platform = setVersion(platform); return platform; } private String getRunningOn(ContainerConfiguration containerConfiguration) { return String.format("%s:%s", containerConfiguration.hostname(), containerConfiguration.port()); } protected Runtime setRuntimeProperties(Runtime runtime) { ApplicationContext applicationContext = ContextProvider.get(); ContainerContext containerContext = applicationContext.container(); ContainerConfiguration containerConfiguration = containerContext.configuration(); String runningOn = getRunningOn(containerConfiguration); runtime.hostedOn(runningOn); runtime.ghnId(containerContext.id()); runtime.status(applicationContext.configuration().mode().toString()); return runtime; } protected Profile setProfileProperties(Profile profile, boolean update) { /* * * Application * CKanDataCatalogue * gCat Configuration created/updated by the service via REST */ profile.category(CATEGORY); profile.name(NAME); profile.description(String.format("gCat configuration %s by the service via REST", update ? "updated" : "created")); return profile; } protected boolean isRootMaster(ServiceEndpoint serviceEndpoint) { Profile profile = serviceEndpoint.profile(); AccessPoint accessPoint = getAccessPoint(profile); Map propertyMap = accessPoint.propertyMap(); if (propertyMap.containsKey(IS_ROOT_MASTER_PROPERTY_KEY)) { if (propertyMap.get(IS_ROOT_MASTER_PROPERTY_KEY).value().trim().equalsIgnoreCase("true")) { return true; } } return false; } protected ServiceEndpoint createServiceEndpoint(ServiceEndpoint serviceEndpoint) throws Exception { boolean update = serviceEndpoint != null; boolean rootMaster = false; if(update) { if(catalogueConfiguration.getSysAdminToken()==null) { Profile profile = serviceEndpoint.profile(); AccessPoint accessPoint = getAccessPoint(profile); Map propertyMap = accessPoint.propertyMap(); // add this host String ckanURL = accessPoint.address(); catalogueConfiguration.setCkanURL(ckanURL); // retrieve sys admin token String encryptedSysAdminToken = propertyMap.get(API_KEY_PROPERTY_KEY).value(); catalogueConfiguration.setSysAdminToken(StringEncrypter.getEncrypter().decrypt(encryptedSysAdminToken)); } rootMaster = isRootMaster(serviceEndpoint); } serviceEndpoint = new ServiceEndpoint(); serviceEndpoint.setId(catalogueConfiguration.getID()); Profile profile = serviceEndpoint.newProfile(); profile = setProfileProperties(profile, update); Platform platform = profile.newPlatform(); setPlatformProperty(platform); Runtime runtime = profile.newRuntime(); runtime = setRuntimeProperties(runtime); Group accessPoints = profile.accessPoints(); AccessPoint accessPoint = accessPoints.add(); Group properties = setAccessPointProperties(accessPoint, update); if(rootMaster) { addProperty(properties, IS_ROOT_MASTER_PROPERTY_KEY, Boolean.toString(rootMaster)); } return serviceEndpoint; } public CatalogueConfiguration createOnIS(ServiceEndpoint serviceEndpoint) throws Exception { RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); String id = catalogueConfiguration.getID(); if(id==null || id.compareTo("")==0) { id = UUID.randomUUID().toString(); catalogueConfiguration.setID(id); } serviceEndpoint = createServiceEndpoint(serviceEndpoint); registryPublisher.create(serviceEndpoint); return catalogueConfiguration; } public CatalogueConfiguration updateOnIS(ServiceEndpoint serviceEndpoint) throws Exception { RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); String id = serviceEndpoint.id(); if(catalogueConfiguration.getID().compareTo(id)!=0) { catalogueConfiguration.setID(id); } serviceEndpoint = createServiceEndpoint(serviceEndpoint); registryPublisher.update(serviceEndpoint); return catalogueConfiguration; } public CatalogueConfiguration createOrUpdateOnIS() throws Exception { ServiceEndpoint serviceEndpoint = getServiceEndpoint(); if(serviceEndpoint!=null) { // It's an update updateOnIS(serviceEndpoint); }else { // It's a create createOnIS(serviceEndpoint); } return catalogueConfiguration; } }