/** * 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.ambari.server.controller.internal; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.orm.entities.ExtensionEntity; import org.apache.ambari.server.state.AutoDeployInfo; import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.DependencyInfo; import org.apache.ambari.server.topology.Cardinality; /** * Encapsulates extension information. * * An extension version is like a stack version but it contains custom services. Linking an extension * version to the current stack version allows the cluster to install the custom services contained in * the extension version. */ public class Extension { /** * Extension name */ private String name; /** * Extension version */ private String version; /** * Map of service name to components */ private Map<String, Collection<String>> serviceComponents = new HashMap<>(); /** * Map of component to service */ private Map<String, String> componentService = new HashMap<>(); /** * Map of component to dependencies */ private Map<String, Collection<DependencyInfo>> dependencies = new HashMap<>(); /** * Map of dependency to conditional service */ private Map<DependencyInfo, String> dependencyConditionalServiceMap = new HashMap<>(); /** * Map of database component name to configuration property which indicates whether * the database in to be managed or if it is an external non-managed instance. * If the value of the config property starts with 'New', the database is determined * to be managed, otherwise it is non-managed. */ private Map<String, String> dbDependencyInfo = new HashMap<>(); /** * Map of component to required cardinality */ private Map<String, String> cardinalityRequirements = new HashMap<>(); /** * Map of component to auto-deploy information */ private Map<String, AutoDeployInfo> componentAutoDeployInfo = new HashMap<>(); /** * Ambari Management Controller, used to obtain Extension definitions */ private final AmbariManagementController controller; /** * Constructor. * * @param extension * the extension (not {@code null}). * @param ambariManagementController * the management controller (not {@code null}). * @throws AmbariException */ public Extension(ExtensionEntity extension, AmbariManagementController ambariManagementController) throws AmbariException { this(extension.getExtensionName(), extension.getExtensionVersion(), ambariManagementController); } /** * Constructor. * * @param name extension name * @param version extension version * * @throws AmbariException an exception occurred getting extension information * for the specified name and version */ //todo: don't pass management controller in constructor public Extension(String name, String version, AmbariManagementController controller) throws AmbariException { this.name = name; this.version = version; this.controller = controller; } /** * Obtain extension name. * * @return extension name */ public String getName() { return name; } /** * Obtain extension version. * * @return extension version */ public String getVersion() { return version; } Map<DependencyInfo, String> getDependencyConditionalServiceMap() { return dependencyConditionalServiceMap; } /** * Get services contained in the extension. * * @return collection of all services for the extension */ public Collection<String> getServices() { return serviceComponents.keySet(); } /** * Get components contained in the extension for the specified service. * * @param service service name * * @return collection of component names for the specified service */ public Collection<String> getComponents(String service) { return serviceComponents.get(service); } /** * Get all service components * * @return map of service to associated components */ public Map<String, Collection<String>> getComponents() { Map<String, Collection<String>> serviceComponents = new HashMap<>(); for (String service : getServices()) { Collection<String> components = new HashSet<>(); components.addAll(getComponents(service)); serviceComponents.put(service, components); } return serviceComponents; } /** * Get info for the specified component. * * @param component component name * * @return component information for the requested component * or null if the component doesn't exist in the extension */ public ComponentInfo getComponentInfo(String component) { ComponentInfo componentInfo = null; String service = getServiceForComponent(component); if (service != null) { try { componentInfo = controller.getAmbariMetaInfo().getComponent( getName(), getVersion(), service, component); } catch (AmbariException e) { // just return null if component doesn't exist } } return componentInfo; } /** * Get the service for the specified component. * * @param component component name * * @return service name that contains tha specified component */ public String getServiceForComponent(String component) { return componentService.get(component); } /** * Get the names of the services which contains the specified components. * * @param components collection of components * * @return collection of services which contain the specified components */ public Collection<String> getServicesForComponents(Collection<String> components) { Set<String> services = new HashSet<>(); for (String component : components) { services.add(getServiceForComponent(component)); } return services; } /** * Return the dependencies specified for the given component. * * @param component component to get dependency information for * * @return collection of dependency information for the specified component */ //todo: full dependency graph public Collection<DependencyInfo> getDependenciesForComponent(String component) { return dependencies.containsKey(component) ? dependencies.get(component) : Collections.<DependencyInfo>emptySet(); } /** * Get the service, if any, that a component dependency is conditional on. * * @param dependency dependency to get conditional service for * * @return conditional service for provided component or null if dependency * is not conditional on a service */ public String getConditionalServiceForDependency(DependencyInfo dependency) { return dependencyConditionalServiceMap.get(dependency); } public String getExternalComponentConfig(String component) { return dbDependencyInfo.get(component); } /** * Obtain the required cardinality for the specified component. */ public Cardinality getCardinality(String component) { return new Cardinality(cardinalityRequirements.get(component)); } /** * Obtain auto-deploy information for the specified component. */ public AutoDeployInfo getAutoDeployInfo(String component) { return componentAutoDeployInfo.get(component); } }