http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java new file mode 100644 index 0000000..b17da30 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionId.java @@ -0,0 +1,160 @@ +/** + * 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.state; + +import org.apache.ambari.server.orm.entities.ExtensionEntity; +import org.apache.ambari.server.utils.VersionUtils; + +/** + * 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 ExtensionId implements Comparable<ExtensionId> { + + private static final String NAME_SEPARATOR = "-"; + + private String extensionName; + private String extensionVersion; + + public ExtensionId() { + extensionName = ""; + extensionVersion = ""; + } + + public ExtensionId(String extensionId) { + parseExtensionIdHelper(this, extensionId); + } + + public ExtensionId(ExtensionInfo extension) { + extensionName = extension.getName(); + extensionVersion = extension.getVersion(); + } + + public ExtensionId(String extensionName, String extensionVersion) { + this(extensionName + NAME_SEPARATOR + extensionVersion); + } + + public ExtensionId(ExtensionEntity entity) { + this(entity.getExtensionName(), entity.getExtensionVersion()); + } + + /** + * @return the extensionName + */ + public String getExtensionName() { + return extensionName; + } + + /** + * @return the extensionVersion + */ + public String getExtensionVersion() { + return extensionVersion; + } + + /** + * @return the extensionVersion + */ + public String getExtensionId() { + if (extensionName.isEmpty() + && extensionVersion.isEmpty()) { + return ""; + } + return extensionName + NAME_SEPARATOR + extensionVersion; + } + + /** + * @param extensionId the extensionVersion to set + */ + public void setExtensionId(String extensionId) { + parseExtensionIdHelper(this, extensionId); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object object) { + if (!(object instanceof ExtensionId)) { + return false; + } + if (this == object) { + return true; + } + ExtensionId s = (ExtensionId) object; + return extensionName.equals(s.extensionName) && extensionVersion.equals(s.extensionVersion); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int result = extensionName != null ? extensionName.hashCode() : 0; + result = 31 * result + (extensionVersion != null ? extensionVersion.hashCode() : 0); + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public int compareTo(ExtensionId other) { + if (this == other) { + return 0; + } + + if (other == null) { + throw new RuntimeException("Cannot compare with a null value."); + } + + int returnValue = getExtensionName().compareTo(other.getExtensionName()); + if (returnValue == 0) { + returnValue = VersionUtils.compareVersions(getExtensionVersion(), other.getExtensionVersion()); + } else { + throw new RuntimeException("ExtensionId with different names cannot be compared."); + } + return returnValue; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return getExtensionId(); + } + + private void parseExtensionIdHelper(ExtensionId extensionVersion, String extensionId) { + if (extensionId == null || extensionId.isEmpty()) { + extensionVersion.extensionName = ""; + extensionVersion.extensionVersion = ""; + return; + } + + int pos = extensionId.indexOf('-'); + if (pos == -1 || (extensionId.length() <= (pos + 1))) { + throw new RuntimeException("Could not parse invalid Extension Id" + ", extensionId=" + extensionId); + } + + extensionVersion.extensionName = extensionId.substring(0, pos); + extensionVersion.extensionVersion = extensionId.substring(pos + 1); + } +}
http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java new file mode 100644 index 0000000..89a6fb5 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ExtensionInfo.java @@ -0,0 +1,208 @@ +/** + * 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.state; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.controller.ExtensionVersionResponse; +import org.apache.ambari.server.stack.Validable; +import org.apache.ambari.server.state.stack.ExtensionMetainfoXml; + +/** + * 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 ExtensionInfo implements Comparable<ExtensionInfo>, Validable{ + private String name; + private String version; + private Collection<ServiceInfo> services; + private String parentExtensionVersion; + + private List<ExtensionMetainfoXml.Stack> stacks; + private List<ExtensionMetainfoXml.Extension> extensions; + private boolean valid = true; + + /** + * + * @return valid xml flag + */ + @Override + public boolean isValid() { + return valid; + } + + /** + * + * @param valid set validity flag + */ + @Override + public void setValid(boolean valid) { + this.valid = valid; + } + + private Set<String> errorSet = new HashSet<String>(); + + @Override + public void addError(String error) { + errorSet.add(error); + } + + @Override + public Collection<String> getErrors() { + return errorSet; + } + + @Override + public void addErrors(Collection<String> errors) { + this.errorSet.addAll(errors); + } + + //private String stackHooksFolder; + + private String upgradesFolder = null; + + private volatile Map<String, PropertyInfo> requiredProperties; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public synchronized Collection<ServiceInfo> getServices() { + if (services == null) services = new ArrayList<ServiceInfo>(); + return services; + } + + public ServiceInfo getService(String name) { + Collection<ServiceInfo> services = getServices(); + for (ServiceInfo service : services) { + if (service.getName().equals(name)) { + return service; + } + } + //todo: exception? + return null; + } + + public synchronized void setServices(Collection<ServiceInfo> services) { + this.services = services; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Extension name:" + name + "\nversion:" + + version + " \nvalid:" + isValid()); + if (services != null) { + sb.append("\n\t\tService:"); + for (ServiceInfo service : services) { + sb.append("\t\t"); + sb.append(service); + } + } + + return sb.toString(); + } + + + @Override + public int hashCode() { + return 31 + name.hashCode() + version.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ExtensionInfo)) { + return false; + } + if (this == obj) { + return true; + } + ExtensionInfo extInfo = (ExtensionInfo) obj; + return getName().equals(extInfo.getName()) && getVersion().equals(extInfo.getVersion()); + } + + public ExtensionVersionResponse convertToResponse() { + Collection<ServiceInfo> serviceInfos = getServices(); + // The collection of service descriptor files. A Set is being used because some Kerberos descriptor + // files contain multiple services, therefore the same File may be encountered more than once. + // For example the YARN directory may contain YARN and MAPREDUCE2 services. + Collection<File> serviceDescriptorFiles = new HashSet<File>(); + if (serviceInfos != null) { + for (ServiceInfo serviceInfo : serviceInfos) { + File file = serviceInfo.getKerberosDescriptorFile(); + if (file != null) { + serviceDescriptorFiles.add(file); + } + } + } + + return new ExtensionVersionResponse(getVersion(), getParentExtensionVersion(), + isValid(), getErrors()); + } + + public String getParentExtensionVersion() { + return parentExtensionVersion; + } + + public void setParentExtensionVersion(String parentExtensionVersion) { + this.parentExtensionVersion = parentExtensionVersion; + } + + @Override + public int compareTo(ExtensionInfo o) { + String myId = name + "-" + version; + String oId = o.name + "-" + o.version; + return myId.compareTo(oId); + } + + public List<ExtensionMetainfoXml.Stack> getStacks() { + return stacks; + } + + public void setStacks(List<ExtensionMetainfoXml.Stack> stacks) { + this.stacks = stacks; + } + + public List<ExtensionMetainfoXml.Extension> getExtensions() { + return extensions; + } + + public void setExtensions(List<ExtensionMetainfoXml.Extension> extensions) { + this.extensions = extensions; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java index 76840ea..6fda8bc 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java @@ -27,6 +27,7 @@ import com.google.common.collect.Multimaps; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.stack.Validable; import org.apache.ambari.server.state.stack.MetricDefinition; +import org.apache.ambari.server.state.stack.StackRoleCommandOrder; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.map.annotate.JsonFilter; @@ -145,6 +146,8 @@ public class ServiceInfo implements Validable{ @XmlTransient private File widgetsDescriptorFile = null; + private StackRoleCommandOrder roleCommandOrder; + @XmlTransient private boolean valid = true; @@ -730,6 +733,14 @@ public String getVersion() { this.widgetsDescriptorFile = widgetsDescriptorFile; } + public StackRoleCommandOrder getRoleCommandOrder() { + return roleCommandOrder; + } + + public void setRoleCommandOrder(StackRoleCommandOrder roleCommandOrder) { + this.roleCommandOrder = roleCommandOrder; + } + /** * @return config types this service contains configuration for, but which are primarily related to another service */ http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java index c7738cd..c30f28f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java @@ -49,6 +49,7 @@ public class StackInfo implements Comparable<StackInfo>, Validable{ private String widgetsDescriptorFileLocation; private List<RepositoryInfo> repositories; private Collection<ServiceInfo> services; + private Collection<ExtensionInfo> extensions; private String parentStackVersion; // stack-level properties private List<PropertyInfo> properties; @@ -161,6 +162,34 @@ public class StackInfo implements Comparable<StackInfo>, Validable{ this.services = services; } + public synchronized Collection<ExtensionInfo> getExtensions() { + if (extensions == null) extensions = new ArrayList<ExtensionInfo>(); + return extensions; + } + + public ExtensionInfo getExtension(String name) { + Collection<ExtensionInfo> extensions = getExtensions(); + for (ExtensionInfo extension : extensions) { + if (extension.getName().equals(name)) { + return extension; + } + } + //todo: exception? + return null; + } + + public ExtensionInfo getExtensionByService(String serviceName) { + Collection<ExtensionInfo> extensions = getExtensions(); + for (ExtensionInfo extension : extensions) { + for (ServiceInfo service : services) { + if (service.getName().equals(serviceName)) + return extension; + } + } + //todo: exception? + return null; + } + public List<PropertyInfo> getProperties() { if (properties == null) properties = new ArrayList<PropertyInfo>(); return properties; http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java new file mode 100644 index 0000000..790e514 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ExtensionMetainfoXml.java @@ -0,0 +1,204 @@ +/** + * 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.state.stack; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import org.apache.ambari.server.stack.Validable; + +/** + * Represents the extension <code>metainfo.xml</code> file. + * + * 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. + */ +@XmlRootElement(name="metainfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class ExtensionMetainfoXml implements Validable{ + + @XmlElement(name="extends") + private String extendsVersion = null; + + @XmlElement(name="versions") + private Version version = new Version(); + + @XmlElement(name="prerequisites") + private Prerequisites prerequisites = new Prerequisites(); + + @XmlAccessorType(XmlAccessType.FIELD) + public static class Prerequisites { + private Prerequisites() { + } + @XmlElementWrapper(name="min-stack-versions") + @XmlElements(@XmlElement(name="stack")) + private List<Stack> stacks = new ArrayList<Stack>(); + + @XmlElementWrapper(name="min-extension-versions") + @XmlElements(@XmlElement(name="extension")) + private List<Extension> extensions = new ArrayList<Extension>(); + + public List<Stack> getStacks() { + return stacks; + } + + public List<Extension> getExtensions() { + return extensions; + } + } + + @XmlTransient + private boolean valid = true; + + /** + * + * @return valid xml flag + */ + @Override + public boolean isValid() { + return valid; + } + + /** + * + * @param valid set validity flag + */ + @Override + public void setValid(boolean valid) { + this.valid = valid; + } + + @XmlTransient + private Set<String> errorSet = new HashSet<String>(); + + @Override + public void addError(String error) { + errorSet.add(error); + } + + @Override + public Collection<String> getErrors() { + return errorSet; + } + + @Override + public void addErrors(Collection<String> errors) { + this.errorSet.addAll(errors); + } + + /** + * @return the parent stack version number + */ + public String getExtends() { + return extendsVersion; + } + + /** + * @return gets the version + */ + public Version getVersion() { + return version; + } + + public List<Stack> getStacks() { + return prerequisites.getStacks(); + } + + public List<Extension> getExtensions() { + return prerequisites.getExtensions(); + } + + @XmlAccessorType(XmlAccessType.FIELD) + public static class Version { + private Version() { + } + private boolean active = false; + private String upgrade = null; + + /** + * @return <code>true</code> if the stack is active + */ + public boolean isActive() { + return active; + } + + /** + * @return the upgrade version number, if set + */ + public String getUpgrade() { + return upgrade; + } + } + + @XmlAccessorType(XmlAccessType.FIELD) + public static class Stack { + private Stack() { + } + private String name = null; + private String version = null; + + /** + * @return the stack name + */ + public String getName() { + return name; + } + + /** + * @return the stack version, this may be something like 1.0.* + */ + public String getVersion() { + return version; + } + } + + @XmlAccessorType(XmlAccessType.FIELD) + public static class Extension { + private Extension() { + } + private String name = null; + private String version = null; + + /** + * @return the extension name + */ + public String getName() { + return name; + } + + /** + * @return the extension version, this may be something like 1.0.* + */ + public String getVersion() { + return version; + } + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java index 418c389..1fa6dcf 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/ServiceMetainfoXml.java @@ -86,6 +86,10 @@ public class ServiceMetainfoXml implements Validable{ public List<ServiceInfo> getServices() { return services; } + + public void setServices(List<ServiceInfo> services) { + this.services = services; + } public String getSchemaVersion() { return schemaVersion; http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java index 13206c0..6da5bd0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java @@ -161,7 +161,6 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { protected static final String PHOENIX_QUERY_SERVER_PRINCIPAL_KEY = "phoenix.queryserver.kerberos.principal"; protected static final String PHOENIX_QUERY_SERVER_KEYTAB_KEY = "phoenix.queryserver.keytab.file"; - private static final String OOZIE_ENV_CONFIG = "oozie-env"; private static final String HIVE_ENV_CONFIG = "hive-env"; private static final String AMS_SITE = "ams-site"; @@ -174,6 +173,10 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { protected static final String HBASE_SITE_CONFIG = "hbase-site"; protected static final String HBASE_SPNEGO_PRINCIPAL_KEY = "hbase.security.authentication.spnego.kerberos.principal"; protected static final String HBASE_SPNEGO_KEYTAB_KEY = "hbase.security.authentication.spnego.kerberos.keytab"; + protected static final String EXTENSION_TABLE = "extension"; + protected static final String EXTENSION_ID_COLUMN = "extension_id"; + protected static final String EXTENSION_LINK_TABLE = "extensionlink"; + protected static final String EXTENSION_LINK_ID_COLUMN = "link_id"; private static final Map<String, Integer> ROLE_ORDER; @@ -265,6 +268,8 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { protected void executeDDLUpdates() throws AmbariException, SQLException { updateAdminPermissionTable(); updateServiceComponentDesiredStateTable(); + createExtensionTable(); + createExtensionLinkTable(); createSettingTable(); updateRepoVersionTableDDL(); updateServiceComponentDesiredStateTableDDL(); @@ -292,7 +297,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { columns.add(new DBColumnInfo("username", String.class, 255, null, false)); columns.add(new DBColumnInfo("password", String.class, 255, null, false)); dbAccessor.createTable(REMOTE_AMBARI_CLUSTER_TABLE, columns, CLUSTER_ID); - dbAccessor.addUniqueConstraint(REMOTE_AMBARI_CLUSTER_TABLE , "unq_remote_ambari_cluster" , CLUSTER_NAME); + dbAccessor.addUniqueConstraint(REMOTE_AMBARI_CLUSTER_TABLE , "UQ_remote_ambari_cluster" , CLUSTER_NAME); addSequence("remote_cluster_id_seq", 1L, false); List<DBColumnInfo> remoteClusterServiceColumns = new ArrayList<>(); @@ -465,6 +470,48 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { } } + private void createExtensionTable() throws SQLException { + List<DBColumnInfo> columns = new ArrayList<>(); + + // Add extension table + LOG.info("Creating " + EXTENSION_TABLE + " table"); + + columns.add(new DBColumnInfo(EXTENSION_ID_COLUMN, Long.class, null, null, false)); + columns.add(new DBColumnInfo("extension_name", String.class, 255, null, false)); + columns.add(new DBColumnInfo("extension_version", String.class, 255, null, false)); + dbAccessor.createTable(EXTENSION_TABLE, columns, EXTENSION_ID_COLUMN); + + // create UNIQUE constraint, ensuring column order matches SQL files + String[] uniqueColumns = new String[] { "extension_name", "extension_version" }; + dbAccessor.addUniqueConstraint(EXTENSION_TABLE, "UQ_extension", uniqueColumns); + + addSequence("extension_id_seq", 0L, false); + } + + private void createExtensionLinkTable() throws SQLException { + List<DBColumnInfo> columns = new ArrayList<>(); + + // Add extension link table + LOG.info("Creating " + EXTENSION_LINK_TABLE + " table"); + + columns.add(new DBColumnInfo(EXTENSION_LINK_ID_COLUMN, Long.class, null, null, false)); + columns.add(new DBColumnInfo("stack_id", Long.class, null, null, false)); + columns.add(new DBColumnInfo(EXTENSION_ID_COLUMN, Long.class, null, null, false)); + dbAccessor.createTable(EXTENSION_LINK_TABLE, columns, EXTENSION_LINK_ID_COLUMN); + + // create UNIQUE constraint, ensuring column order matches SQL files + String[] uniqueColumns = new String[] { "stack_id", EXTENSION_ID_COLUMN }; + dbAccessor.addUniqueConstraint(EXTENSION_LINK_TABLE, "UQ_extension_link", uniqueColumns); + + dbAccessor.addFKConstraint(EXTENSION_LINK_TABLE, "FK_extensionlink_extension_id", + EXTENSION_ID_COLUMN, EXTENSION_TABLE, EXTENSION_ID_COLUMN, false); + + dbAccessor.addFKConstraint(EXTENSION_LINK_TABLE, "FK_extensionlink_stack_id", + "stack_id", STACK_TABLE, "stack_id", false); + + addSequence("link_id_seq", 0L, false); + } + private void createSettingTable() throws SQLException { List<DBColumnInfo> columns = new ArrayList<>(); @@ -1429,7 +1476,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { // create UNIQUE constraint, ensuring column order matches SQL files String[] uniqueColumns = new String[] { "component_name", "service_name", "cluster_id" }; - dbAccessor.addUniqueConstraint(SERVICE_COMPONENT_DS_TABLE, "unq_scdesiredstate_name", + dbAccessor.addUniqueConstraint(SERVICE_COMPONENT_DS_TABLE, "UQ_scdesiredstate_name", uniqueColumns); // add FKs back to SCDS in both HCDS and HCS tables http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index 257ca42..aa8a39e 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -22,7 +22,23 @@ CREATE TABLE stack( stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)); + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)); + +CREATE TABLE extension( + extension_id BIGINT NOT NULL, + extension_name VARCHAR(255) NOT NULL, + extension_version VARCHAR(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY (extension_id), + CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version)); + +CREATE TABLE extensionlink( + link_id BIGINT NOT NULL, + stack_id BIGINT NOT NULL, + extension_id BIGINT NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY (link_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id), + CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id)); CREATE TABLE adminresourcetype ( resource_type_id INTEGER NOT NULL, @@ -176,7 +192,7 @@ CREATE TABLE servicecomponentdesiredstate ( service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id)); @@ -789,7 +805,7 @@ CREATE TABLE remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)); + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)); CREATE TABLE remoteambariclusterservice( id BIGINT NOT NULL, @@ -1092,6 +1108,10 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) union all select 'stack_id_seq', 0 FROM SYSIBM.SYSDUMMY1 union all + select 'extension_id_seq', 0 FROM SYSIBM.SYSDUMMY1 + union all + select 'link_id_seq', 0 FROM SYSIBM.SYSDUMMY1 + union all select 'topology_host_info_id_seq', 0 FROM SYSIBM.SYSDUMMY1 union all select 'topology_host_request_id_seq', 0 FROM SYSIBM.SYSDUMMY1 http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index 9b68174..3be1299 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -32,7 +32,23 @@ CREATE TABLE stack( stack_name VARCHAR(100) NOT NULL, stack_version VARCHAR(100) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)); + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)); + +CREATE TABLE extension( + extension_id BIGINT NOT NULL, + extension_name VARCHAR(255) NOT NULL, + extension_version VARCHAR(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY (extension_id), + CONSTRAINT UQ_extension UNIQUE (extension_name, extension_version)); + +CREATE TABLE extensionlink( + link_id BIGINT NOT NULL, + stack_id BIGINT NOT NULL, + extension_id BIGINT NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY (link_id), + CONSTRAINT UQ_extension_link UNIQUE (stack_id, extension_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id)); CREATE TABLE adminresourcetype ( resource_type_id INTEGER NOT NULL, @@ -176,7 +192,7 @@ CREATE TABLE servicecomponentdesiredstate ( service_name VARCHAR(100) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id)); @@ -796,7 +812,7 @@ CREATE TABLE remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)); + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)); CREATE TABLE remoteambariclusterservice( id BIGINT NOT NULL, @@ -1061,6 +1077,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES ('upgrade_group_id_seq', 0), ('upgrade_item_id_seq', 0), ('stack_id_seq', 0), + ('extension_id_seq', 0), + ('link_id_seq', 0), ('widget_id_seq', 0), ('widget_layout_id_seq', 0), ('topology_host_info_id_seq', 0), http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index 362c714..6bbb282 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -22,7 +22,23 @@ CREATE TABLE stack( stack_name VARCHAR2(255) NOT NULL, stack_version VARCHAR2(255) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)); + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)); + +CREATE TABLE extension( + extension_id NUMERIC(19) NOT NULL, + extension_name VARCHAR2(255) NOT NULL, + extension_version VARCHAR2(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY (extension_id), + CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version)); + +CREATE TABLE extensionlink( + link_id NUMERIC(19) NOT NULL, + stack_id NUMERIC(19) NOT NULL, + extension_id NUMERIC(19) NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY (link_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id), + CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id)); CREATE TABLE adminresourcetype ( resource_type_id NUMBER(10) NOT NULL, @@ -167,7 +183,7 @@ CREATE TABLE servicecomponentdesiredstate ( service_name VARCHAR2(255) NOT NULL, recovery_enabled SMALLINT DEFAULT 0 NOT NULL, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id)); @@ -786,7 +802,7 @@ CREATE TABLE remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)); + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)); CREATE TABLE remoteambariclusterservice( id NUMBER(19) NOT NULL, @@ -1051,6 +1067,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_id_ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_group_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_item_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('stack_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('extension_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('link_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_layout_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('topology_host_info_id_seq', 0); http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index 04a4361..b13c121 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -22,7 +22,23 @@ CREATE TABLE stack( stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)); + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)); + +CREATE TABLE extension( + extension_id BIGINT NOT NULL, + extension_name VARCHAR(255) NOT NULL, + extension_version VARCHAR(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY (extension_id), + CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version)); + +CREATE TABLE extensionlink( + link_id BIGINT NOT NULL, + stack_id BIGINT NOT NULL, + extension_id BIGINT NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY (link_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id), + CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id)); CREATE TABLE adminresourcetype ( resource_type_id INTEGER NOT NULL, @@ -176,7 +192,7 @@ CREATE TABLE servicecomponentdesiredstate ( service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id)); @@ -788,7 +804,7 @@ CREATE TABLE remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)); + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)); CREATE TABLE remoteambariclusterservice( id BIGINT NOT NULL, @@ -1054,6 +1070,8 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES ('widget_layout_id_seq', 0), ('upgrade_item_id_seq', 0), ('stack_id_seq', 0), + ('extension_id_seq', 0), + ('link_id_seq', 0), ('topology_host_info_id_seq', 0), ('topology_host_request_id_seq', 0), ('topology_host_task_id_seq', 0), http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql index 21e6cec..fd14e80 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql @@ -33,10 +33,28 @@ CREATE TABLE ambari.stack( stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version) + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version) ); GRANT ALL PRIVILEGES ON TABLE ambari.stack TO :username; +CREATE TABLE ambari.extension( + extension_id BIGINT NOT NULL, + extension_name VARCHAR(255) NOT NULL, + extension_version VARCHAR(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY (extension_id), + CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version)); +GRANT ALL PRIVILEGES ON TABLE ambari.extension TO :username; + +CREATE TABLE ambari.extensionlink( + link_id BIGINT NOT NULL, + stack_id BIGINT NOT NULL, + extension_id BIGINT NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY (link_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES ambari.stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES ambari.extension(extension_id), + CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id)); +GRANT ALL PRIVILEGES ON TABLE ambari.extensionlink TO :username; + CREATE TABLE ambari.adminresourcetype ( resource_type_id INTEGER NOT NULL, resource_type_name VARCHAR(255) NOT NULL, @@ -215,7 +233,7 @@ CREATE TABLE ambari.servicecomponentdesiredstate ( service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES ambari.stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES ambari.clusterservices (service_name, cluster_id) ); @@ -924,7 +942,7 @@ CREATE TABLE ambari.remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name) + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name) ); GRANT ALL PRIVILEGES ON TABLE ambari.remoteambaricluster TO :username; @@ -1216,6 +1234,8 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value) VALUES ('widget_layout_id_seq', 0), ('upgrade_item_id_seq', 0), ('stack_id_seq', 0), + ('extension_id_seq', 0), + ('link_id_seq', 0), ('topology_host_info_id_seq', 0), ('topology_host_request_id_seq', 0), ('topology_host_task_id_seq', 0), http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql index 24c1b63..0574c2b 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -21,7 +21,23 @@ CREATE TABLE stack( stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)); + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)); + +CREATE TABLE extension( + extension_id NUMERIC(19) NOT NULL, + extension_name VARCHAR(255) NOT NULL, + extension_version VARCHAR(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY (extension_id), + CONSTRAINT UQ_extension UNIQUE(extension_name, extension_version)); + +CREATE TABLE extensionlink( + link_id NUMERIC(19) NOT NULL, + stack_id NUMERIC(19) NOT NULL, + extension_id NUMERIC(19) NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY (link_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id), + CONSTRAINT UQ_extension_link UNIQUE(stack_id, extension_id)); CREATE TABLE adminresourcetype ( resource_type_id INTEGER NOT NULL, @@ -165,7 +181,7 @@ CREATE TABLE servicecomponentdesiredstate ( service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id)); @@ -785,7 +801,7 @@ CREATE TABLE remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)); + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)); CREATE TABLE remoteambariclusterservice( id NUMERIC(19) NOT NULL, @@ -1050,6 +1066,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_id_ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_group_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_item_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('stack_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('extension_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('link_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('widget_layout_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('topology_host_info_id_seq', 0); http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql index cef4866..02becf2 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -34,7 +34,23 @@ CREATE TABLE stack( stack_name VARCHAR(255) NOT NULL, stack_version VARCHAR(255) NOT NULL, CONSTRAINT PK_stack PRIMARY KEY CLUSTERED (stack_id), - CONSTRAINT unq_stack UNIQUE (stack_name, stack_version)); + CONSTRAINT UQ_stack UNIQUE (stack_name, stack_version)); + +CREATE TABLE extension( + extension_id BIGINT NOT NULL, + extension_name VARCHAR(255) NOT NULL, + extension_version VARCHAR(255) NOT NULL, + CONSTRAINT PK_extension PRIMARY KEY CLUSTERED (extension_id), + CONSTRAINT UQ_extension UNIQUE (extension_name, extension_version)); + +CREATE TABLE extensionlink( + link_id BIGINT NOT NULL, + stack_id BIGINT NOT NULL, + extension_id BIGINT NOT NULL, + CONSTRAINT PK_extensionlink PRIMARY KEY CLUSTERED (link_id), + CONSTRAINT FK_extensionlink_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id), + CONSTRAINT FK_extensionlink_extension_id FOREIGN KEY (extension_id) REFERENCES extension(extension_id), + CONSTRAINT UQ_extension_link UNIQUE (stack_id, extension_id); CREATE TABLE adminresourcetype ( resource_type_id INTEGER NOT NULL, @@ -189,7 +205,7 @@ CREATE TABLE servicecomponentdesiredstate ( service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), - CONSTRAINT unq_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), + CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id)); @@ -806,7 +822,7 @@ CREATE TABLE remoteambaricluster( url VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, CONSTRAINT PK_remote_ambari_cluster PRIMARY KEY (cluster_id), - CONSTRAINT unq_remote_ambari_cluster UNIQUE (name)); + CONSTRAINT UQ_remote_ambari_cluster UNIQUE (name)); CREATE TABLE remoteambariclusterservice( id BIGINT NOT NULL, @@ -1078,6 +1094,8 @@ BEGIN TRANSACTION ('widget_layout_id_seq', 0), ('upgrade_item_id_seq', 0), ('stack_id_seq', 0), + ('extension_id_seq', 0), + ('link_id_seq', 0), ('topology_host_info_id_seq', 0), ('topology_host_request_id_seq', 0), ('topology_host_task_id_seq', 0), http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/META-INF/persistence.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml index 5671dcf..d44f484 100644 --- a/ambari-server/src/main/resources/META-INF/persistence.xml +++ b/ambari-server/src/main/resources/META-INF/persistence.xml @@ -33,6 +33,8 @@ <class>org.apache.ambari.server.orm.entities.ConfigGroupEntity</class> <class>org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity</class> <class>org.apache.ambari.server.orm.entities.ExecutionCommandEntity</class> + <class>org.apache.ambari.server.orm.entities.ExtensionEntity</class> + <class>org.apache.ambari.server.orm.entities.ExtensionLinkEntity</class> <class>org.apache.ambari.server.orm.entities.GroupEntity</class> <class>org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity</class> <class>org.apache.ambari.server.orm.entities.HostComponentStateEntity</class> http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/extensions/README.txt ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/extensions/README.txt b/ambari-server/src/main/resources/extensions/README.txt new file mode 100644 index 0000000..865dfc0 --- /dev/null +++ b/ambari-server/src/main/resources/extensions/README.txt @@ -0,0 +1,31 @@ +Extensions should include a folder with the extension name. +Subfolders of the extension name folder represents different +extension versions. + +For a sample extension MY_EXT 1.0, I would create subfolders: MY_EXT/1.0 + +Within each extension version folder, there should be both a metainfo.xml +file and a services folder. The metainfo.xml should contain the +stack versions with which the extension version are compatible. + +For example the following metainfo.xml shows an extension that is +compatible with both HDP 2.4 and HDP 2.5: + +<metainfo> + <prerequisites> + <min-stack-versions> + <stack> + <name>HDP</name> + <version>2.4</version> + </stack> + <stack> + <name>HDP</name> + <version>2.5</version> + </stack> + </min-stack-versions> + </prerequisites> +</metainfo> + +The services folder will contain all services that are part of the +extension version. The contents of those service folders will be the +same as what you would find in under a stack version's services folder. http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/key_properties.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/key_properties.json b/ambari-server/src/main/resources/key_properties.json index 8069349..df2006a 100644 --- a/ambari-server/src/main/resources/key_properties.json +++ b/ambari-server/src/main/resources/key_properties.json @@ -79,13 +79,27 @@ "StackService": "StackServiceComponents/service_name", "StackServiceComponent": "StackServiceComponents/component_name" }, - "StackServiceComponentDependency": { + "StackServiceComponentDependency": { "Stack": "Dependencies/stack_name", "StackVersion": "Dependencies/stack_version", "StackService": "Dependencies/dependent_service_name", "StackServiceComponent": "Dependencies/dependent_component_name", "StackServiceComponentDependency": "Dependencies/component_name" }, + "ExtensionLink": { + "ExtensionLink": "ExtensionLink/link_id", + "Stack": "ExtensionLink/stack_name", + "StackVersion": "ExtensionLink/stack_version", + "Extension": "ExtensionLink/extension_name", + "ExtensionVersion": "ExtensionLink/extension_version" + }, + "Extension": { + "Extension": "Extensions/extension_name" + }, + "ExtensionVersion": { + "Extension": "Versions/extension_name", + "ExtensionVersion": "Versions/extension_version" + }, "DRFeed": { "DRFeed": "Feed/name" }, http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/main/resources/properties.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json index eac0dbd..f471628 100644 --- a/ambari-server/src/main/resources/properties.json +++ b/ambari-server/src/main/resources/properties.json @@ -265,6 +265,26 @@ "auto_deploy/enabled", "auto_deploy/location" ], + "ExtensionLink": [ + "ExtensionLink/link_id", + "ExtensionLink/stack_name", + "ExtensionLink/stack_version", + "ExtensionLink/extension_name", + "ExtensionLink/extension_version", + "_" + ], + "Extension":[ + "Extensions/extension_name", + "_" + ], + "ExtensionVersion":[ + "Versions/extension_name", + "Versions/extension_version", + "Versions/valid", + "Versions/extension-errors", + "Versions/parent_extension_version", + "_" + ], "DRFeed":[ "Feed/name", "Feed/description", @@ -469,10 +489,10 @@ "StackConfigurationDependency/dependency_name", "_" ], - "KerberosDescriptor":[ - "KerberosDescriptors/kerberos_descriptor_name", - "KerberosDescriptors/kerberos_descriptor_text", - "_" - ] + "KerberosDescriptor":[ + "KerberosDescriptors/kerberos_descriptor_name", + "KerberosDescriptors/kerberos_descriptor_text", + "_" + ] } http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java new file mode 100644 index 0000000..97fd2b5 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ExtensionsServiceTest.java @@ -0,0 +1,119 @@ +/** + * 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.api.services; + +import org.apache.ambari.server.api.resources.ResourceInstance; +import org.apache.ambari.server.api.services.parsers.RequestBodyParser; +import org.apache.ambari.server.api.services.serializers.ResultSerializer; +import org.easymock.EasyMock; +import org.junit.Test; + + +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.same; +import static org.junit.Assert.assertEquals; + +/** +* Unit tests for ExtensionsService. +*/ +public class ExtensionsServiceTest extends BaseServiceTest { + + @Override + public List<ServiceTestInvocation> getTestInvocations() throws Exception { + List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>(); + + // getExtension + ExtensionsService service = new TestExtensionsService("extensionName", null); + Method m = service.getClass().getMethod("getExtension", String.class, HttpHeaders.class, UriInfo.class, String.class); + Object[] args = new Object[] {null, getHttpHeaders(), getUriInfo(), "extensionName"}; + listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null)); + + //getExtensions + service = new TestExtensionsService(null, null); + m = service.getClass().getMethod("getExtensions", String.class, HttpHeaders.class, UriInfo.class); + args = new Object[] {null, getHttpHeaders(), getUriInfo()}; + listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null)); + + // getExtensionVersion + service = new TestExtensionsService("extensionName", "extensionVersion"); + m = service.getClass().getMethod("getExtensionVersion", String.class, HttpHeaders.class, UriInfo.class, String.class, String.class); + args = new Object[] {null, getHttpHeaders(), getUriInfo(), "extensionName", "extensionVersion"}; + listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null)); + + // getExtensionVersions + service = new TestExtensionsService("extensionName", null); + m = service.getClass().getMethod("getExtensionVersions", String.class, HttpHeaders.class, UriInfo.class, String.class); + args = new Object[] {null, getHttpHeaders(), getUriInfo(), "extensionName"}; + listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null)); + + return listInvocations; + } + + private class TestExtensionsService extends ExtensionsService { + + private String m_extensionId; + private String m_extensionVersion; + + private TestExtensionsService(String extensionName, String extensionVersion) { + m_extensionId = extensionName; + m_extensionVersion = extensionVersion; + } + + @Override + ResourceInstance createExtensionResource(String extensionName) { + assertEquals(m_extensionId, extensionName); + return getTestResource(); + } + + @Override + ResourceInstance createExtensionVersionResource(String extensionName, String extensionVersion) { + assertEquals(m_extensionId, extensionName); + assertEquals(m_extensionVersion, extensionVersion); + return getTestResource(); + } + + @Override + RequestFactory getRequestFactory() { + return getTestRequestFactory(); + } + + @Override + protected RequestBodyParser getBodyParser() { + return getTestBodyParser(); + } + + @Override + protected ResultSerializer getResultSerializer() { + return getTestResultSerializer(); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java new file mode 100644 index 0000000..8959e4d --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ExtensionResourceProviderTest.java @@ -0,0 +1,91 @@ +/** + * 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 org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.ExtensionRequest; +import org.apache.ambari.server.controller.ExtensionResponse; +import org.apache.ambari.server.controller.spi.Request; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.spi.ResourceProvider; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * ExtensionResourceProvider Test + */ +public class ExtensionResourceProviderTest { + @Test + public void testGetResources() throws Exception { + Resource.Type type = Resource.Type.Extension; + + AmbariManagementController managementController = createMock(AmbariManagementController.class); + + Set<ExtensionResponse> allResponse = new HashSet<ExtensionResponse>(); + allResponse.add(new ExtensionResponse("Extension1")); + allResponse.add(new ExtensionResponse("Extension2")); + + // set expectations + expect(managementController.getExtensions(EasyMock.<Set<ExtensionRequest>>anyObject())).andReturn(allResponse).once(); + + // replay + replay(managementController); + + ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider( + type, + PropertyHelper.getPropertyIds(type), + PropertyHelper.getKeyPropertyIds(type), + managementController); + + Set<String> propertyIds = new HashSet<String>(); + + propertyIds.add(ExtensionResourceProvider.EXTENSION_NAME_PROPERTY_ID); + + // create the request + Request request = PropertyHelper.getReadRequest(propertyIds); + + // get all ... no predicate + Set<Resource> resources = provider.getResources(request, null); + + Assert.assertEquals(2, resources.size()); + + + Set<String> extensionNames = new HashSet<String>(); + extensionNames.add("Extension1"); + extensionNames.add("Extension2"); + + for (Resource resource : resources) { + String extensionName = (String) resource.getPropertyValue(ExtensionResourceProvider.EXTENSION_NAME_PROPERTY_ID); + Assert.assertTrue(extensionNames.contains(extensionName)); + } + + // verify + verify(managementController); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java index a02311a..f21b250 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ComponentModuleTest.java @@ -495,7 +495,7 @@ public class ComponentModuleTest { ComponentModule component = new ComponentModule(info); ComponentModule parentComponent = new ComponentModule(parentInfo); - component.resolve(parentComponent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap()); + component.resolve(parentComponent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap(), Collections.<String, ExtensionModule>emptyMap()); return component; } http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java index 8fcc76e..38176aa 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/QuickLinksConfigurationModuleTest.java @@ -118,11 +118,11 @@ public class QuickLinksConfigurationModuleTest { QuickLinksConfigurationModule parentModule = new QuickLinksConfigurationModule(parentQuiclinksFile); QuickLinksConfigurationModule childModule = new QuickLinksConfigurationModule(childQuickLinksFile); - childModule.resolve(parentModule, null, null); + childModule.resolve(parentModule, null, null, null); QuickLinks parentQuickLinks = parentModule.getModuleInfo().getQuickLinksConfigurationMap().get(QuickLinksConfigurationModule.QUICKLINKS_CONFIGURATION_KEY); QuickLinks childQuickLinks = childModule.getModuleInfo().getQuickLinksConfigurationMap().get(QuickLinksConfigurationModule.QUICKLINKS_CONFIGURATION_KEY); return new QuickLinks[]{parentQuickLinks, childQuickLinks}; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java index c9bcf60..304fd5c 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java @@ -1211,7 +1211,7 @@ public class ServiceModuleTest { } private void resolveService(ServiceModule service, ServiceModule parent) throws AmbariException { - service.resolve(parent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap()); + service.resolve(parent, Collections.<String, StackModule>emptyMap(), Collections.<String, ServiceModule>emptyMap(), Collections.<String, ExtensionModule>emptyMap()); // during runtime this would be called by the Stack module when it's resolve completed service.finalizeModule(); parent.finalizeModule(); http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java index 969e07c..1d73ff3 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerCommonServicesTest.java @@ -29,14 +29,19 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.metadata.ActionMetadata; +import org.apache.ambari.server.orm.dao.ExtensionDAO; +import org.apache.ambari.server.orm.dao.ExtensionLinkDAO; import org.apache.ambari.server.orm.dao.MetainfoDAO; import org.apache.ambari.server.orm.dao.StackDAO; +import org.apache.ambari.server.orm.entities.ExtensionEntity; +import org.apache.ambari.server.orm.entities.ExtensionLinkEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.CommandScriptDefinition; import org.apache.ambari.server.state.ComponentInfo; @@ -58,6 +63,8 @@ public class StackManagerCommonServicesTest { private static StackManager stackManager; private static MetainfoDAO metaInfoDao; private static StackDAO stackDao; + private static ExtensionDAO extensionDao; + private static ExtensionLinkDAO linkDao; private static ActionMetadata actionMetadata; private static OsFamily osFamily; @@ -72,17 +79,22 @@ public class StackManagerCommonServicesTest { String commonServices = ClassLoader.getSystemClassLoader().getResource( "common-services").getPath(); - return createTestStackManager(stack, commonServices); + String extensions = ClassLoader.getSystemClassLoader().getResource( + "extensions").getPath(); + return createTestStackManager(stack, commonServices, extensions); } public static StackManager createTestStackManager(String stackRoot, - String commonServicesRoot) throws Exception { + String commonServicesRoot, String extensionRoot) throws Exception { // todo: dao , actionMetaData expectations metaInfoDao = createNiceMock(MetainfoDAO.class); stackDao = createNiceMock(StackDAO.class); + extensionDao = createNiceMock(ExtensionDAO.class); + linkDao = createNiceMock(ExtensionLinkDAO.class); actionMetadata = createNiceMock(ActionMetadata.class); Configuration config = createNiceMock(Configuration.class); StackEntity stackEntity = createNiceMock(StackEntity.class); + ExtensionEntity extensionEntity = createNiceMock(ExtensionEntity.class); expect(config.getSharedResourcesDirPath()).andReturn( ClassLoader.getSystemClassLoader().getResource("").getPath()).anyTimes(); @@ -91,13 +103,25 @@ public class StackManagerCommonServicesTest { stackDao.find(EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce(); - replay(config, stackDao); + + expect( + extensionDao.find(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(extensionEntity).atLeastOnce(); + + List<ExtensionLinkEntity> list = Collections.emptyList(); + expect( + linkDao.findByStack(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce(); + + replay(config, stackDao, extensionDao, linkDao); + osFamily = new OsFamily(config); replay(metaInfoDao, actionMetadata); StackManager stackManager = new StackManager(new File(stackRoot), new File( - commonServicesRoot), osFamily, false, metaInfoDao, actionMetadata, stackDao); + commonServicesRoot), new File(extensionRoot), osFamily, true, metaInfoDao, + actionMetadata, stackDao, extensionDao, linkDao); EasyMock.verify( config, stackDao ); http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java new file mode 100644 index 0000000..659ae12 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerExtensionTest.java @@ -0,0 +1,131 @@ +/** + * 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.stack; + +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.ambari.server.metadata.ActionMetadata; +import org.apache.ambari.server.orm.dao.ExtensionDAO; +import org.apache.ambari.server.orm.dao.ExtensionLinkDAO; +import org.apache.ambari.server.orm.dao.MetainfoDAO; +import org.apache.ambari.server.orm.dao.StackDAO; +import org.apache.ambari.server.orm.entities.ExtensionEntity; +import org.apache.ambari.server.orm.entities.ExtensionLinkEntity; +import org.apache.ambari.server.orm.entities.StackEntity; +import org.apache.ambari.server.state.ExtensionInfo; +import org.apache.ambari.server.state.ServiceInfo; +import org.apache.ambari.server.state.StackInfo; +import org.apache.ambari.server.state.stack.OsFamily; +import org.easymock.EasyMock; +import org.junit.Test; + +/** + * StackManager extension unit tests. + */ +public class StackManagerExtensionTest { + + @Test + public void testExtensions() throws Exception { + MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class); + StackDAO stackDao = createNiceMock(StackDAO.class); + ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class); + ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class); + ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class); + OsFamily osFamily = createNiceMock(OsFamily.class); + StackEntity stackEntity = createNiceMock(StackEntity.class); + ExtensionEntity extensionEntity = createNiceMock(ExtensionEntity.class); + ExtensionLinkEntity linkEntity = createNiceMock(ExtensionLinkEntity.class); + List<ExtensionLinkEntity> list = new ArrayList<ExtensionLinkEntity>(); + list.add(linkEntity); + + expect( + stackDao.find(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce(); + + expect( + extensionDao.find(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(extensionEntity).atLeastOnce(); + + expect( + linkDao.findByStack(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce(); + + expect( + linkEntity.getExtension()).andReturn(extensionEntity).atLeastOnce(); + + expect( + extensionEntity.getExtensionName()).andReturn("EXT").atLeastOnce(); + + expect( + extensionEntity.getExtensionVersion()).andReturn("0.2").atLeastOnce(); + + replay(actionMetadata, stackDao, metaInfoDao, osFamily, extensionDao, linkDao, extensionEntity, linkEntity); + + String stacks = ClassLoader.getSystemClassLoader().getResource("stacks_with_extensions").getPath(); + String common = ClassLoader.getSystemClassLoader().getResource("common-services").getPath(); + String extensions = ClassLoader.getSystemClassLoader().getResource("extensions").getPath(); + + StackManager stackManager = new StackManager(new File(stacks), + new File(common), new File(extensions), osFamily, false, + metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao); + + ExtensionInfo extension = stackManager.getExtension("EXT", "0.1"); + assertNull("EXT 0.1's parent: " + extension.getParentExtensionVersion(), extension.getParentExtensionVersion()); + assertNotNull(extension.getService("OOZIE2")); + ServiceInfo oozie = extension.getService("OOZIE2"); + assertNotNull("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder()); + assertTrue("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder().contains("extensions/EXT/0.1/services/OOZIE2/package")); + assertEquals(oozie.getVersion(), "3.2.0"); + + extension = stackManager.getExtension("EXT", "0.2"); + assertNotNull("EXT 0.2's parent: " + extension.getParentExtensionVersion(), extension.getParentExtensionVersion()); + assertEquals("EXT 0.2's parent: " + extension.getParentExtensionVersion(), "0.1", extension.getParentExtensionVersion()); + assertNotNull(extension.getService("OOZIE2")); + oozie = extension.getService("OOZIE2"); + assertNotNull("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder()); + assertTrue("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder().contains("extensions/EXT/0.1/services/OOZIE2/package")); + assertEquals(oozie.getVersion(), "4.0.0"); + + StackInfo stack = stackManager.getStack("HDP", "0.2"); + assertNotNull(stack.getService("OOZIE2")); + oozie = stack.getService("OOZIE2"); + assertNotNull("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder()); + assertTrue("Package dir is " + oozie.getServicePackageFolder(), oozie.getServicePackageFolder().contains("extensions/EXT/0.1/services/OOZIE2/package")); + assertEquals(oozie.getVersion(), "4.0.0"); + + assertTrue("Extensions found: " + stack.getExtensions().size(), stack.getExtensions().size() == 1); + extension = stack.getExtensions().iterator().next(); + assertEquals("Extension name: " + extension.getName(), extension.getName(), "EXT"); + assertEquals("Extension version: " + extension.getVersion(), extension.getVersion(), "0.2"); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/9ce79716/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java index 55a3c46..ca24cd9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/StackManagerMiscTest.java @@ -28,11 +28,16 @@ import static org.junit.Assert.fail; import java.io.File; import java.util.Collection; +import java.util.Collections; +import java.util.List; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.metadata.ActionMetadata; +import org.apache.ambari.server.orm.dao.ExtensionDAO; +import org.apache.ambari.server.orm.dao.ExtensionLinkDAO; import org.apache.ambari.server.orm.dao.MetainfoDAO; import org.apache.ambari.server.orm.dao.StackDAO; +import org.apache.ambari.server.orm.entities.ExtensionLinkEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.StackInfo; import org.apache.ambari.server.state.stack.OsFamily; @@ -48,6 +53,8 @@ public class StackManagerMiscTest { public void testCycleDetection() throws Exception { MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class); StackDAO stackDao = createNiceMock(StackDAO.class); + ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class); + ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class); ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class); OsFamily osFamily = createNiceMock(OsFamily.class); StackEntity stackEntity = createNiceMock(StackEntity.class); @@ -56,13 +63,18 @@ public class StackManagerMiscTest { stackDao.find(EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce(); - replay(actionMetadata, stackDao, metaInfoDao, osFamily); + List<ExtensionLinkEntity> list = Collections.emptyList(); + expect( + linkDao.findByStack(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce(); + + replay(actionMetadata, stackDao, extensionDao, linkDao, metaInfoDao, osFamily); try { String stacksCycle1 = ClassLoader.getSystemClassLoader().getResource("stacks_with_cycle").getPath(); - StackManager stackManager = new StackManager(new File(stacksCycle1), - null, osFamily, false, metaInfoDao, actionMetadata, stackDao); + StackManager stackManager = new StackManager(new File(stacksCycle1), null, null, osFamily, false, + metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao); fail("Expected exception due to cyclic stack"); } catch (AmbariException e) { @@ -74,7 +86,7 @@ public class StackManagerMiscTest { "stacks_with_cycle2").getPath(); StackManager stackManager = new StackManager(new File(stacksCycle2), - null, osFamily, true, metaInfoDao, actionMetadata, stackDao); + null, null, osFamily, true, metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao); fail("Expected exception due to cyclic stack"); } catch (AmbariException e) { @@ -91,6 +103,8 @@ public class StackManagerMiscTest { public void testGetServiceInfoFromSingleStack() throws Exception { MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class); StackDAO stackDao = createNiceMock(StackDAO.class); + ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class); + ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class); ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class); OsFamily osFamily = createNiceMock(OsFamily.class); StackEntity stackEntity = createNiceMock(StackEntity.class); @@ -102,14 +116,18 @@ public class StackManagerMiscTest { stackDao.find(EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce(); - replay(metaInfoDao, stackDao, actionMetadata, osFamily); + List<ExtensionLinkEntity> list = Collections.emptyList(); + expect( + linkDao.findByStack(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce(); + + replay(metaInfoDao, stackDao, extensionDao, linkDao, actionMetadata, osFamily); String singleStack = ClassLoader.getSystemClassLoader().getResource("single_stack").getPath(); StackManager stackManager = new StackManager(new File(singleStack.replace( - StackManager.PATH_DELIMITER, File.separator)), - null, osFamily, false, metaInfoDao, actionMetadata, stackDao); - + StackManager.PATH_DELIMITER, File.separator)), null, null, osFamily, false, metaInfoDao, + actionMetadata, stackDao, extensionDao, linkDao); Collection<StackInfo> stacks = stackManager.getStacks(); assertEquals(1, stacks.size()); @@ -126,6 +144,8 @@ public class StackManagerMiscTest { public void testCircularDependencyForServiceUpgrade() throws Exception { MetainfoDAO metaInfoDao = createNiceMock(MetainfoDAO.class); StackDAO stackDao = createNiceMock(StackDAO.class); + ExtensionDAO extensionDao = createNiceMock(ExtensionDAO.class); + ExtensionLinkDAO linkDao = createNiceMock(ExtensionLinkDAO.class); ActionMetadata actionMetadata = createNiceMock(ActionMetadata.class); OsFamily osFamily = createNiceMock(OsFamily.class); StackEntity stackEntity = createNiceMock(StackEntity.class); @@ -134,13 +154,18 @@ public class StackManagerMiscTest { stackDao.find(EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))).andReturn(stackEntity).atLeastOnce(); - replay(actionMetadata, stackDao, metaInfoDao, osFamily); + List<ExtensionLinkEntity> list = Collections.emptyList(); + expect( + linkDao.findByStack(EasyMock.anyObject(String.class), + EasyMock.anyObject(String.class))).andReturn(list).atLeastOnce(); + + replay(metaInfoDao, stackDao, extensionDao, linkDao, actionMetadata, osFamily); try { String upgradeCycle = ClassLoader.getSystemClassLoader().getResource("stacks_with_upgrade_cycle").getPath(); - StackManager stackManager = new StackManager(new File(upgradeCycle), - null, osFamily, false, metaInfoDao, actionMetadata, stackDao); + StackManager stackManager = new StackManager(new File(upgradeCycle), null, null, osFamily, false, + metaInfoDao, actionMetadata, stackDao, extensionDao, linkDao); fail("Expected exception due to cyclic service upgrade xml"); } catch (AmbariException e) {
