http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java index bb6a93c..f63c962 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java @@ -123,6 +123,12 @@ public class ViewConfig { private String dataVersion; /** + * Enable views to display cluster options in case of no cluster config properties. + */ + @XmlElement(name="cluster-config-options") + private String clusterConfigOptions; + + /** * The view class. */ private Class<? extends ViewDataMigrator> dataMigratorClass = null; @@ -450,4 +456,13 @@ public class ViewConfig { public List<PermissionConfig> getPermissions() { return permissions == null ? Collections.<PermissionConfig>emptyList() : permissions; } + + /** + * Enables views to display cluster options in case of no cluster config properties + * + * @return clusterConfigOptions + */ + public String getClusterConfigOptions() { + return clusterConfigOptions; + } }
http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 415e06b..d77a0b3 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -567,6 +567,7 @@ CREATE TABLE viewinstance ( xml_driven CHAR(1), alter_names SMALLINT NOT NULL DEFAULT 1, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI', short_url BIGINT, CONSTRAINT PK_viewinstance PRIMARY KEY (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id), @@ -601,7 +602,7 @@ CREATE TABLE viewparameter ( label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), - cluster_config VARCHAR(255), + cluster_config VARCHAR(255) , required CHAR(1), masked CHAR(1), CONSTRAINT PK_viewparameter PRIMARY KEY (view_name, name), @@ -778,6 +779,26 @@ CREATE TABLE setting ( CONSTRAINT PK_setting PRIMARY KEY (id) ); +-- Remote Cluster table + +CREATE TABLE remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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)); + +CREATE TABLE remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id) +); + +-- Remote Cluster table ends -- upgrade tables CREATE TABLE upgrade ( @@ -1094,7 +1115,11 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) union all select 'blueprint_setting_id_seq', 0 FROM SYSIBM.SYSDUMMY1 union all - select 'ambari_operation_history_id_seq', 0 FROM SYSIBM.SYSDUMMY1; + select 'ambari_operation_history_id_seq', 0 FROM SYSIBM.SYSDUMMY1 + union all + select 'remote_cluster_id_seq', 0 FROM SYSIBM.SYSDUMMY1 + union all + select 'remote_cluster_service_id_seq', 0 FROM SYSIBM.SYSDUMMY1; INSERT INTO adminresourcetype (resource_type_id, resource_type_name) http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 e3ce816..22413e0 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -575,6 +575,7 @@ CREATE TABLE viewinstance ( xml_driven CHAR(1), alter_names TINYINT(1) NOT NULL DEFAULT 1, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI', short_url BIGINT, CONSTRAINT PK_viewinstance PRIMARY KEY (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id), @@ -785,6 +786,26 @@ CREATE TABLE setting ( CONSTRAINT PK_setting PRIMARY KEY (id) ); +-- Remote Cluster table + +CREATE TABLE remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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)); + +CREATE TABLE remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id) +); + +-- Remote Cluster table ends -- upgrade tables CREATE TABLE upgrade ( @@ -1053,7 +1074,9 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES ('servicecomponentdesiredstate_id_seq', 0), ('servicecomponent_history_id_seq', 0), ('blueprint_setting_id_seq', 0), - ('ambari_operation_history_id_seq', 0); + ('ambari_operation_history_id_seq', 0), + ('remote_cluster_id_seq', 0), + ('remote_cluster_service_id_seq', 0),; INSERT INTO adminresourcetype (resource_type_id, resource_type_name) VALUES (1, 'AMBARI'), http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 cd88e8b..6000d24 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -566,6 +566,7 @@ CREATE TABLE viewinstance ( xml_driven CHAR(1), alter_names NUMBER(1) DEFAULT 1 NOT NULL, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) DEFAULT 'LOCAL_AMBARI' NOT NULL, short_url NUMBER, CONSTRAINT PK_viewinstance PRIMARY KEY (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id), @@ -775,6 +776,26 @@ CREATE TABLE setting ( CONSTRAINT PK_setting PRIMARY KEY (id) ); +-- Remote Cluster table + +CREATE TABLE remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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)); + +CREATE TABLE remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id) +); + +-- Remote Cluster table ends -- upgrade tables CREATE TABLE upgrade ( @@ -1044,6 +1065,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomp INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('ambari_operation_history_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_service_id_seq', 0); INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', '${ambariSchemaVersion}'); http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 108e33e..67bd38a 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -567,6 +567,7 @@ CREATE TABLE viewinstance ( xml_driven CHAR(1), alter_names SMALLINT NOT NULL DEFAULT 1, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI', short_url BIGINT, CONSTRAINT PK_viewinstance PRIMARY KEY (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id), @@ -777,6 +778,26 @@ CREATE TABLE setting ( update_timestamp BIGINT NOT NULL, CONSTRAINT PK_setting PRIMARY KEY (id)); +-- Remote Cluster table + +CREATE TABLE remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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)); + +CREATE TABLE remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id) +); + +-- Remote Cluster table ends -- upgrade tables CREATE TABLE upgrade ( @@ -1044,7 +1065,9 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES ('servicecomponentdesiredstate_id_seq', 0), ('servicecomponent_history_id_seq', 0), ('blueprint_setting_id_seq', 0), - ('ambari_operation_history_id_seq', 0); + ('ambari_operation_history_id_seq', 0), + ('remote_cluster_id_seq', 0), + ('remote_cluster_service_id_seq', 0); INSERT INTO adminresourcetype (resource_type_id, resource_type_name) VALUES (1, 'AMBARI'), http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 566da84..ea7ab7a 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 @@ -668,6 +668,7 @@ CREATE TABLE ambari.viewinstance ( xml_driven CHAR(1), alter_names SMALLINT NOT NULL DEFAULT 1, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI', short_url BIGINT, CONSTRAINT PK_viewinstance PRIMARY KEY (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES ambari.viewurl(url_id), @@ -913,6 +914,30 @@ CREATE TABLE ambari.setting ( ); GRANT ALL PRIVILEGES ON TABLE ambari.setting TO :username; +-- Remote Cluster table + +CREATE TABLE ambari.remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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) +); +GRANT ALL PRIVILEGES ON TABLE ambari.remoteambaricluster TO :username; + +CREATE TABLE ambari.remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.remoteambaricluster(cluster_id) +); +GRANT ALL PRIVILEGES ON TABLE ambari.remoteambariclusterservice TO :username; + +-- Remote Cluster table ends + -- upgrade tables CREATE TABLE ambari.upgrade ( upgrade_id BIGINT NOT NULL, @@ -1202,7 +1227,9 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value) VALUES ('servicecomponentdesiredstate_id_seq', 0), ('servicecomponent_history_id_seq', 0), ('blueprint_setting_id_seq', 0), - ('ambari_operation_history_id_seq', 0); + ('ambari_operation_history_id_seq', 0), + ('remote_cluster_id_seq', 0), + ('remote_cluster_service_id_seq', 0); INSERT INTO ambari.adminresourcetype (resource_type_id, resource_type_name) VALUES (1, 'AMBARI'), http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 bd5d1ae..1c3393e 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -564,6 +564,7 @@ CREATE TABLE viewinstance ( xml_driven CHAR(1), alter_names BIT NOT NULL DEFAULT 1, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI', short_url NUMERIC, CONSTRAINT PK_viewinstance PRIMARY KEY (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id), @@ -774,6 +775,26 @@ CREATE TABLE setting ( CONSTRAINT PK_setting PRIMARY KEY (id) ); +-- Remote Cluster table + +CREATE TABLE remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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)); + +CREATE TABLE remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id) +); + +-- Remote Cluster table ends -- upgrade tables CREATE TABLE upgrade ( @@ -1043,6 +1064,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomp INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('ambari_operation_history_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_service_id_seq', 0); insert into adminresourcetype (resource_type_id, resource_type_name) select 1, 'AMBARI' http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 20c706a..2245f77 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -574,6 +574,7 @@ CREATE TABLE viewinstance ( xml_driven CHAR(1), alter_names BIT NOT NULL DEFAULT 1, cluster_handle VARCHAR(255), + cluster_type VARCHAR(100) NOT NULL DEFAULT 'LOCAL_AMBARI', short_url BIGINT, CONSTRAINT PK_viewinstance PRIMARY KEY CLUSTERED (view_instance_id), CONSTRAINT FK_instance_url_id FOREIGN KEY (short_url) REFERENCES viewurl(url_id), @@ -795,6 +796,26 @@ CREATE TABLE setting ( CONSTRAINT PK_setting PRIMARY KEY (id) ); +-- Remote Cluster table + +CREATE TABLE remoteambaricluster( + cluster_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + 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)); + +CREATE TABLE remoteambariclusterservice( + id BIGINT NOT NULL, + cluster_id BIGINT NOT NULL, + service_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_remote_ambari_service PRIMARY KEY (id), + CONSTRAINT FK_remote_ambari_cluster_id FOREIGN KEY (cluster_id) REFERENCES remoteambaricluster(cluster_id) +); + +-- Remote Cluster table ends -- upgrade tables CREATE TABLE upgrade ( @@ -1068,7 +1089,9 @@ BEGIN TRANSACTION ('servicecomponentdesiredstate_id_seq', 0), ('servicecomponent_history_id_seq', 0), ('blueprint_setting_id_seq', 0), - ('ambari_operation_history_id_seq', 0); + ('ambari_operation_history_id_seq', 0), + ('remote_cluster_id_seq', 0), + ('remote_cluster_service_id_seq', 0); insert into adminresourcetype (resource_type_id, resource_type_name) values http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/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 ce563cb..5671dcf 100644 --- a/ambari-server/src/main/resources/META-INF/persistence.xml +++ b/ambari-server/src/main/resources/META-INF/persistence.xml @@ -93,6 +93,8 @@ <class>org.apache.ambari.server.orm.entities.TopologyLogicalTaskEntity</class> <class>org.apache.ambari.server.orm.entities.SettingEntity</class> <class>org.apache.ambari.server.orm.entities.KerberosDescriptorEntity</class> + <class>org.apache.ambari.server.orm.entities.RemoteAmbariClusterEntity</class> + <class>org.apache.ambari.server.orm.entities.RemoteAmbariClusterServiceEntity</class> <properties> <property name="eclipselink.cache.size.default" value="10000" /> http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RemoteClusterResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RemoteClusterResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RemoteClusterResourceProviderTest.java new file mode 100644 index 0000000..546f155 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RemoteClusterResourceProviderTest.java @@ -0,0 +1,193 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.predicate.EqualsPredicate; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.apache.ambari.server.orm.dao.RemoteAmbariClusterDAO; +import org.apache.ambari.server.orm.entities.RemoteAmbariClusterEntity; +import org.apache.ambari.server.orm.entities.RemoteAmbariClusterServiceEntity; +import org.apache.ambari.server.security.TestAuthenticationFactory; +import org.apache.ambari.server.view.RemoteAmbariClusterRegistry; +import org.easymock.Capture; +import org.junit.After; +import org.junit.Test; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.newCapture; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +public class RemoteClusterResourceProviderTest { + + @After + public void clearAuthentication() { + SecurityContextHolder.getContext().setAuthentication(null); + } + + @Test + public void testToResource() throws Exception { + RemoteClusterResourceProvider provider = new RemoteClusterResourceProvider(); + Set<String> propertyIds = new HashSet<String>(); + propertyIds.add(RemoteClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID); + propertyIds.add(RemoteClusterResourceProvider.CLUSTER_URL_PROPERTY_ID); + propertyIds.add(RemoteClusterResourceProvider.USERNAME_PROPERTY_ID); + propertyIds.add(RemoteClusterResourceProvider.PASSWORD_PROPERTY_ID); + propertyIds.add(RemoteClusterResourceProvider.SERVICES_PROPERTY_ID); + + RemoteAmbariClusterServiceEntity service1 = createNiceMock(RemoteAmbariClusterServiceEntity.class); + expect(service1.getServiceName()).andReturn("service1").once(); + + RemoteAmbariClusterServiceEntity service2 = createNiceMock(RemoteAmbariClusterServiceEntity.class); + expect(service2.getServiceName()).andReturn("service2").once(); + + List<RemoteAmbariClusterServiceEntity> serviceList = new ArrayList<RemoteAmbariClusterServiceEntity>(); + serviceList.add(service1); + serviceList.add(service2); + + RemoteAmbariClusterEntity entity = createNiceMock(RemoteAmbariClusterEntity.class); + expect(entity.getName()).andReturn("test").once(); + expect(entity.getUrl()).andReturn("url").once(); + expect(entity.getUsername()).andReturn("user").once(); + expect(entity.getServices()).andReturn(serviceList).once(); + + replay(service1, service2, entity); + + List<String> services = new ArrayList<String>(); + services.add("service1"); + services.add("service2"); + + Resource resource = provider.toResource(propertyIds, entity); + assertEquals(resource.getPropertyValue(RemoteClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID), "test"); + assertEquals(resource.getPropertyValue(RemoteClusterResourceProvider.CLUSTER_URL_PROPERTY_ID), "url"); + assertEquals(resource.getPropertyValue(RemoteClusterResourceProvider.USERNAME_PROPERTY_ID), "user"); + assertEquals(resource.getPropertyValue(RemoteClusterResourceProvider.SERVICES_PROPERTY_ID), services); + verify(service1, service2, entity); + } + + @Test + public void testCreateResourcesAsAdministrator() throws Exception { + testCreateResources(TestAuthenticationFactory.createAdministrator()); + } + + static void setField(Field field, Object newValue) throws Exception { + field.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(null, newValue); + } + + private void testCreateResources(Authentication authentication) throws Exception { + + RemoteClusterResourceProvider provider = new RemoteClusterResourceProvider(); + + RemoteAmbariClusterDAO clusterDAO = createMock(RemoteAmbariClusterDAO.class); + setField(RemoteClusterResourceProvider.class.getDeclaredField("remoteAmbariClusterDAO"), clusterDAO); + + RemoteAmbariClusterRegistry clusterRegistry = createMock(RemoteAmbariClusterRegistry.class); + setField(RemoteClusterResourceProvider.class.getDeclaredField("remoteAmbariClusterRegistry"), clusterRegistry); + + Set<Map<String, Object>> properties = new HashSet<>(); + Map<String, Object> propertyMap = new HashMap<>(); + propertyMap.put(RemoteClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID, "test"); + propertyMap.put(RemoteClusterResourceProvider.CLUSTER_URL_PROPERTY_ID, "url"); + propertyMap.put(RemoteClusterResourceProvider.USERNAME_PROPERTY_ID, "username"); + propertyMap.put(RemoteClusterResourceProvider.PASSWORD_PROPERTY_ID, "password"); + + RemoteAmbariClusterServiceEntity service1 = createNiceMock(RemoteAmbariClusterServiceEntity.class); + expect(service1.getServiceName()).andReturn("service1").once(); + + RemoteAmbariClusterServiceEntity service2 = createNiceMock(RemoteAmbariClusterServiceEntity.class); + expect(service2.getServiceName()).andReturn("service2").once(); + + List<RemoteAmbariClusterServiceEntity> serviceList = new ArrayList<RemoteAmbariClusterServiceEntity>(); + serviceList.add(service1); + serviceList.add(service2); + + expect(clusterDAO.findByName("test")).andReturn(null).anyTimes(); + Capture<RemoteAmbariClusterEntity> clusterEntityCapture = newCapture(); + + clusterRegistry.saveOrUpdate(capture(clusterEntityCapture),eq(false)); + + replay(clusterRegistry, clusterDAO, service1, service2); + + properties.add(propertyMap); + + SecurityContextHolder.getContext().setAuthentication(authentication); + + provider.createResources(PropertyHelper.getCreateRequest(properties, null)); + + RemoteAmbariClusterEntity clusterEntity = clusterEntityCapture.getValue(); + assertEquals(clusterEntity.getName(), "test"); + assertEquals(clusterEntity.getPassword(), "password"); + assertEquals(clusterEntity.getUrl(), "url"); + assertEquals(clusterEntity.getUsername(), "username"); + + } + + @Test + public void testDeleteResources() throws Exception { + RemoteClusterResourceProvider provider = new RemoteClusterResourceProvider(); + RemoteAmbariClusterDAO clusterDAO = createNiceMock(RemoteAmbariClusterDAO.class); + RemoteAmbariClusterEntity clusterEntity = new RemoteAmbariClusterEntity(); + + setField(RemoteClusterResourceProvider.class.getDeclaredField("remoteAmbariClusterDAO"), clusterDAO); + + EqualsPredicate equalsPredicate = new EqualsPredicate(RemoteClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID,"test"); + + RemoteAmbariClusterRegistry clusterRegistry = createMock(RemoteAmbariClusterRegistry.class); + setField(RemoteClusterResourceProvider.class.getDeclaredField("remoteAmbariClusterRegistry"), clusterRegistry); + + Set<Map<String, Object>> properties = new HashSet<>(); + Map<String, Object> propertyMap = new HashMap<>(); + propertyMap.put(RemoteClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID,"test"); + + expect(clusterDAO.findByName("test")).andReturn(clusterEntity); + clusterRegistry.delete(clusterEntity); + + replay(clusterDAO); + + properties.add(propertyMap); + + SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator()); + + provider.deleteResources(PropertyHelper.getCreateRequest(properties, null),equalsPredicate); + + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java index 78a910a..f36e640 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java @@ -243,6 +243,22 @@ public class UpgradeCatalog240Test { dbAccessor.addFKConstraint(UpgradeCatalog240.VIEWINSTANCE_TABLE, "FK_instance_url_id", UpgradeCatalog240.SHORT_URL_COLUMN, UpgradeCatalog240.VIEWURL_TABLE, "url_id", false); + Capture<DBAccessor.DBColumnInfo> viewInstanceClusterType = newCapture(); + dbAccessor.addColumn(eq(UpgradeCatalog240.VIEWINSTANCE_TABLE), capture(viewInstanceClusterType)); + + // Test remote Cluster Tables + Capture<List<DBAccessor.DBColumnInfo>> capturedRemoteAmbariClusterColumns = EasyMock.newCapture(); + dbAccessor.createTable(eq(UpgradeCatalog240.REMOTE_AMBARI_CLUSTER_TABLE), capture(capturedRemoteAmbariClusterColumns),anyString()); + dbAccessor.addUniqueConstraint(UpgradeCatalog240.REMOTE_AMBARI_CLUSTER_TABLE , "unq_remote_ambari_cluster" , UpgradeCatalog240.CLUSTER_NAME); + expect(dbAccessor.getConnection()).andReturn(connection); + expect(connection.createStatement()).andReturn(statement); + + Capture<List<DBAccessor.DBColumnInfo>> capturedRemoteClusterServiceColumns = EasyMock.newCapture(); + dbAccessor.createTable(eq(UpgradeCatalog240.REMOTE_AMBARI_CLUSTER_SERVICE_TABLE), capture(capturedRemoteClusterServiceColumns),anyString()); + dbAccessor.addFKConstraint(UpgradeCatalog240.REMOTE_AMBARI_CLUSTER_SERVICE_TABLE, "FK_remote_ambari_cluster_id", + UpgradeCatalog240.CLUSTER_ID, UpgradeCatalog240.REMOTE_AMBARI_CLUSTER_TABLE, UpgradeCatalog240.CLUSTER_ID, false); + expect(dbAccessor.getConnection()).andReturn(connection); + expect(connection.createStatement()).andReturn(statement); replay(dbAccessor, configuration, connection, statement, resultSet); @@ -403,6 +419,20 @@ public class UpgradeCatalog240Test { Assert.assertNotNull(capturedViewUrlColumsValue); Assert.assertEquals(capturedViewUrlColumsValue.size(),3); + // Verify cluster_type column + DBAccessor.DBColumnInfo viewInstanceEntityClusterTypeValue = viewInstanceClusterType.getValue(); + Assert.assertNotNull(viewInstanceClusterType); + Assert.assertEquals("cluster_type", viewInstanceEntityClusterTypeValue.getName()); + Assert.assertEquals(String.class, viewInstanceEntityClusterTypeValue.getType()); + + List<DBAccessor.DBColumnInfo> capturedRemoteAmbariClusterColumnsValue = capturedRemoteAmbariClusterColumns.getValue(); + Assert.assertNotNull(capturedRemoteAmbariClusterColumnsValue); + Assert.assertEquals(capturedRemoteAmbariClusterColumnsValue.size(),5); + + List<DBAccessor.DBColumnInfo> capturedRemoteClusterServiceColumnsValue = capturedRemoteClusterServiceColumns.getValue(); + Assert.assertNotNull(capturedRemoteClusterServiceColumnsValue); + Assert.assertEquals(capturedRemoteClusterServiceColumnsValue.size(),3); + verify(dbAccessor); } http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-server/src/test/java/org/apache/ambari/server/view/RemoteAmbariClusterTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/RemoteAmbariClusterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/RemoteAmbariClusterTest.java new file mode 100644 index 0000000..ce8fe7d --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/RemoteAmbariClusterTest.java @@ -0,0 +1,90 @@ +/** + * 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.view; + +import org.apache.ambari.server.orm.entities.RemoteAmbariClusterEntity; +import org.apache.ambari.view.AmbariStreamProvider; +import org.easymock.IAnswer; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Map; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isNull; +import static org.easymock.EasyMock.replay; +import static org.junit.Assert.assertEquals; + +public class RemoteAmbariClusterTest { + + @Rule + public ExpectedException thrown= ExpectedException.none(); + + + @Test + public void testGetConfigurationValue() throws Exception { + + AmbariStreamProvider clusterStreamProvider = createNiceMock(AmbariStreamProvider.class); + + final String desiredConfigsString = "{\"Clusters\": {\"desired_configs\": {\"test-site\": {\"tag\": \"TAG\"}}}}"; + final String configurationString = "{\"items\": [{\"properties\": {\"test.property.name\": \"test property value\"}}]}"; + final int[] desiredConfigPolls = {0}; + final int[] testConfigPolls = {0}; + + expect(clusterStreamProvider.readFrom(eq( "?fields=services/ServiceInfo,hosts,Clusters"), + eq("GET"), (String) isNull(), (Map<String, String>) anyObject())).andAnswer(new IAnswer<InputStream>() { + @Override + public InputStream answer() throws Throwable { + desiredConfigPolls[0] += 1; + return new ByteArrayInputStream(desiredConfigsString.getBytes()); + } + }).anyTimes(); + + expect(clusterStreamProvider.readFrom(eq( "/configurations?(type=test-site&tag=TAG)"), + eq("GET"), (String)isNull(), (Map<String, String>) anyObject())).andAnswer(new IAnswer<InputStream>() { + @Override + public InputStream answer() throws Throwable { + testConfigPolls[0] += 1; + return new ByteArrayInputStream(configurationString.getBytes()); + } + }).anyTimes(); + + RemoteAmbariClusterEntity entity = createNiceMock(RemoteAmbariClusterEntity.class); + + replay(clusterStreamProvider,entity); + + RemoteAmbariCluster cluster = new RemoteAmbariCluster("Test", clusterStreamProvider); + + String value = cluster.getConfigurationValue("test-site", "test.property.name"); + assertEquals(value, "test property value"); + assertEquals(desiredConfigPolls[0], 1); + assertEquals(testConfigPolls[0], 1); + + value = cluster.getConfigurationValue("test-site", "test.property.name"); + assertEquals(value, "test property value"); + assertEquals(desiredConfigPolls[0], 1); // cache hit + assertEquals(testConfigPolls[0], 1); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-server/src/test/java/org/apache/ambari/server/view/ViewAmbariStreamProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewAmbariStreamProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewAmbariStreamProviderTest.java index 8549d4a..98b57f0 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewAmbariStreamProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewAmbariStreamProviderTest.java @@ -69,7 +69,7 @@ public class ViewAmbariStreamProviderTest { ViewAmbariStreamProvider viewAmbariStreamProvider = new ViewAmbariStreamProvider(streamProvider, sessionManager, controller); - Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", "params", headers, true)); + Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", "params", headers)); verify(streamProvider, sessionManager, urlConnection, inputStream); } @@ -104,7 +104,7 @@ public class ViewAmbariStreamProviderTest { ViewAmbariStreamProvider viewAmbariStreamProvider = new ViewAmbariStreamProvider(streamProvider, sessionManager, controller); - Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", body, headers, true)); + Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", body, headers)); verify(streamProvider, sessionManager, urlConnection, inputStream); } @@ -139,7 +139,7 @@ public class ViewAmbariStreamProviderTest { ViewAmbariStreamProvider viewAmbariStreamProvider = new ViewAmbariStreamProvider(streamProvider, sessionManager, controller); - Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", body, headers, true)); + Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", body, headers)); verify(streamProvider, sessionManager, urlConnection, inputStream); } @@ -174,7 +174,7 @@ public class ViewAmbariStreamProviderTest { ViewAmbariStreamProvider viewAmbariStreamProvider = new ViewAmbariStreamProvider(streamProvider, sessionManager, controller); - Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", body, headers, true)); + Assert.assertEquals(inputStream, viewAmbariStreamProvider.readFrom("spec", "requestMethod", body, headers)); verify(streamProvider, sessionManager, urlConnection, inputStream); } http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java index a41e137..f318dab 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java @@ -57,6 +57,7 @@ public class ViewConfigTest { " <system>true</system>\n" + " <icon64>/this/is/the/icon/url/icon64.png</icon64>\n" + " <icon>/this/is/the/icon/url/icon.png</icon>\n" + + " <cluster-config-options>AMBARI-ONLY</cluster-config-options>\n" + " <data-migrator-class>org.apache.ambari.server.view.configuration.ViewConfigTest$MyDataMigrator</data-migrator-class>" + " <validator-class>org.apache.ambari.server.view.configuration.ViewConfigTest$MyValidator</validator-class>" + " <masker-class>org.apache.ambari.server.view.DefaultMasker</masker-class>" + @@ -352,6 +353,12 @@ public class ViewConfigTest { Assert.assertEquals("2.0.0", config.getMaxAmbariVersion()); } + @Test + public void testGetClusterConfigOptions() throws Exception { + ViewConfig config = getConfig(); + Assert.assertEquals("AMBARI-ONLY",config.getClusterConfigOptions()); + } + public static ViewConfig getConfig() throws JAXBException { return getConfig(xml); } http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/java/org/apache/ambari/view/AmbariClusterStreamProvider.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/AmbariClusterStreamProvider.java b/ambari-views/src/main/java/org/apache/ambari/view/AmbariClusterStreamProvider.java new file mode 100644 index 0000000..a48749a --- /dev/null +++ b/ambari-views/src/main/java/org/apache/ambari/view/AmbariClusterStreamProvider.java @@ -0,0 +1,90 @@ +/** + * 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.view; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +/** + * Provider of Input stream for Ambari cluster + */ +public interface AmbariClusterStreamProvider { + + + /** + * Read from the input stream specified by the given path for cluster on Ambari server. + * Base path will be /api/v1/clusters/${clusterName} + * + * @param path the String to parse as an Ambari cluster endpoint (e.g. /configurations) + * @param requestMethod the HTTP method (GET,POST,PUT,etc.). + * @param body the body of the request; may be null + * @param headers the headers of the request; may be null + * + * @return the input stream + * + * @throws IOException, AmbariHttpException + */ + public InputStream readFromCluster(String path, String requestMethod, String body, Map<String, String> headers) throws IOException, AmbariHttpException; + + /** + * Read from the input stream specified by the given path for cluster on Ambari server. + * Base path will be /api/v1/clusters/${clusterName} + * + * @param path the String to parse as an Ambari cluster endpoint (e.g. /configurations) + * @param requestMethod the HTTP method (GET,POST,PUT,etc.). + * @param body the body of the request; may be null + * @param headers the headers of the request; may be null + * + * @return the input stream + * + * @throws IOException, AmbariHttpException + */ + public InputStream readFromCluster(String path, String requestMethod, InputStream body, Map<String, String> headers) throws IOException, AmbariHttpException; + + /** + * Read from the input stream specified by the given path for cluster on the Ambari server. + * + * @param path the String to parse as an Ambari endpoint (e.g. /api/v1) + * @param requestMethod the HTTP method (GET,POST,PUT,etc.). + * @param body the body of the request; may be null + * @param headers the headers of the request; may be null + * + * @return the input stream + * + * @throws java.io.IOException if an error occurred connecting to the server + * AmbariHttpException if response to url is unsuccessful + */ + public InputStream readFromAmbari(String path, String requestMethod, String body, Map<String, String> headers) throws IOException, AmbariHttpException; + + /** + * Read from the input stream specified by the given path for cluster on the Ambari server. + * + * @param path the String to parse as an Ambari endpoint (e.g. /api/v1) + * @param requestMethod the HTTP method (GET,POST,PUT,etc.). + * @param body the body of the request; may be null + * @param headers the headers of the request; may be null + * + * @return the input stream + * + * @throws java.io.IOException if an error occurred connecting to the server , + * AmbariHttpException if response to url is unsuccessful + */ + public InputStream readFromAmbari(String path, String requestMethod, InputStream body, Map<String, String> headers) throws IOException, AmbariHttpException; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/java/org/apache/ambari/view/AmbariHttpException.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/AmbariHttpException.java b/ambari-views/src/main/java/org/apache/ambari/view/AmbariHttpException.java new file mode 100644 index 0000000..60c8e29 --- /dev/null +++ b/ambari-views/src/main/java/org/apache/ambari/view/AmbariHttpException.java @@ -0,0 +1,41 @@ +/** + * 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.view; + +/** + * Ambari Http Exception : used to indicate unsuccessful response of url + */ +public class AmbariHttpException extends Exception { + + private int responseCode ; + + public AmbariHttpException(String message, int responseCode) { + super(message); + this.responseCode = responseCode; + } + + /** + * Get the Error code + * + * @return responseCode + */ + public int getResponseCode() { + return responseCode; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/java/org/apache/ambari/view/AmbariStreamProvider.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/AmbariStreamProvider.java b/ambari-views/src/main/java/org/apache/ambari/view/AmbariStreamProvider.java index ce91676..ec9e70c 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/AmbariStreamProvider.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/AmbariStreamProvider.java @@ -33,14 +33,13 @@ public interface AmbariStreamProvider { * @param requestMethod the HTTP method (GET,POST,PUT,etc.). * @param body the body of the request; may be null * @param headers the headers of the request; may be null - * @param useAmbariSession indicates that the current Ambari session cookie should be set for the request * * @return the input stream * * @throws java.io.IOException if an error occurred connecting to the server */ public InputStream readFrom(String path, String requestMethod, String body, - Map<String, String> headers, boolean useAmbariSession) throws IOException; + Map<String, String> headers) throws IOException,AmbariHttpException; /** * Read from the input stream specified by the given path on the Ambari server. @@ -49,12 +48,11 @@ public interface AmbariStreamProvider { * @param requestMethod the HTTP method (GET,POST,PUT,etc.). * @param body the body of the request; may be null * @param headers the headers of the request; may be null - * @param useAmbariSession indicates that the current Ambari session cookie should be set for the request * * @return the input stream * * @throws java.io.IOException if an error occurred connecting to the server */ public InputStream readFrom(String path, String requestMethod, InputStream body, - Map<String, String> headers, boolean useAmbariSession) throws IOException; + Map<String, String> headers) throws IOException,AmbariHttpException; } http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/java/org/apache/ambari/view/ClusterType.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ClusterType.java b/ambari-views/src/main/java/org/apache/ambari/view/ClusterType.java new file mode 100644 index 0000000..bab2c41 --- /dev/null +++ b/ambari-views/src/main/java/org/apache/ambari/view/ClusterType.java @@ -0,0 +1,40 @@ +/** + * 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.view; + +/** + * Cluster type enums + */ +public enum ClusterType { + + /** + * Local ambari cluster + */ + LOCAL_AMBARI, + + /** + * Remote Ambari managed cluster + */ + REMOTE_AMBARI, + + /** + * Used when view is not managed by cluster + */ + NONE +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java index 7b7b025..7aaa799 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java @@ -172,6 +172,14 @@ public interface ViewContext { public AmbariStreamProvider getAmbariStreamProvider(); /** + * Get Ambari stream provider attached as cluster to the view + * If view is not attached to ambari managed cluster then it will be null + * + * @return stream provider for the cluster + */ + public AmbariStreamProvider getAmbariClusterStreamProvider(); + + /** * Get a data store for view persistence entities. * * @return a data store; null if no instance is associated http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java index 0c3d3ce..cea4c88 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java @@ -61,6 +61,13 @@ public interface ViewInstanceDefinition { */ public String getClusterHandle(); + /** + * Get the type of cluster the view instance is attached to + * + * @return clusterType the type of cluster for cluster handle + */ + public ClusterType getClusterType(); + /** * Indicates whether or not the view instance should be visible. @@ -89,4 +96,5 @@ public interface ViewInstanceDefinition { * @return the view definition */ public ViewDefinition getViewDefinition(); + } http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/ambari-views/src/main/resources/view.xsd ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/resources/view.xsd b/ambari-views/src/main/resources/view.xsd index 04902e9..cc18950 100644 --- a/ambari-views/src/main/resources/view.xsd +++ b/ambari-views/src/main/resources/view.xsd @@ -347,6 +347,11 @@ <xs:documentation>The Masker class for masking view parameters.</xs:documentation> </xs:annotation> </xs:element> + <xs:element type="xs:string" name="cluster-config-options" minOccurs="0" maxOccurs="1"> + <xs:annotation> + <xs:documentation>Enable views to display cluster options in case of no cluster config properties.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element type="xs:string" name="data-migrator-class" minOccurs="0" maxOccurs="1"> <xs:annotation> <xs:documentation>The data migration class.</xs:documentation> http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java ---------------------------------------------------------------------- diff --git a/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java b/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java index 7f1d489..718c5a5 100644 --- a/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java +++ b/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java @@ -118,8 +118,6 @@ public class ConfigurationService { public Response readLatestConfiguration() { Response response = null; try { - validateViewConfiguration(); - String versionTag = getVersionTag(); JSONObject configurations = getConfigurationFromAmbari(versionTag); response = Response.ok(configurations).build(); @@ -143,8 +141,6 @@ public class ConfigurationService { public Response readClusterInfo() { Response response = null; try { - validateViewConfiguration(); - JSONObject configurations = readFromCluster(""); response = Response.ok(configurations).build(); } catch (WebApplicationException ex) { @@ -167,8 +163,6 @@ public class ConfigurationService { public Response readAllConfigurations() { Response response = null; try { - validateViewConfiguration(); - JSONObject responseJSON = readFromCluster(CONFIGURATION_URL); response = Response.ok( responseJSON ).build(); } catch (WebApplicationException ex) { @@ -191,8 +185,6 @@ public class ConfigurationService { public Response readConfigurationByTag(@PathParam("tag") String tag) { Response response = null; try { - validateViewConfiguration(); - JSONObject configurations = getConfigurationFromAmbari(tag); response = Response.ok(configurations).build(); } catch (WebApplicationException ex) { @@ -265,8 +257,7 @@ public class ConfigurationService { * @return if <code>true</code>, the user is an operator; otherwise <code>false</code> */ private boolean isOperator() { - validateViewConfiguration(); - + // first check if the user is an CLUSTER.ADMINISTRATOR String url = String.format(CLUSTER_OPERATOR_PRIVILEGE_URL, context.getUsername()); JSONObject json = readFromCluster(url); @@ -316,33 +307,6 @@ public class ConfigurationService { return jsonObject; } - /** - * Validates the view configuration properties. - * - * @throws MisconfigurationFormattedException if one of the required view configuration properties are not set - */ - private void validateViewConfiguration() { - // check if we are cluster config'd, if so, just go - if (ambariApi.isLocalCluster()) { - return; - } - - String hostname = context.getProperties().get("ambari.server.url"); - if (hostname == null) { - throw new MisconfigurationFormattedException("ambari.server.url"); - } - - String username = context.getProperties().get("ambari.server.username"); - if (username == null) { - throw new MisconfigurationFormattedException("ambari.server.username"); - } - - String password = context.getProperties().get("ambari.server.password"); - if (password == null) { - throw new MisconfigurationFormattedException("ambari.server.password"); - } - } - private JSONObject getConfigurationFromAmbari(String versionTag) { String url = String.format(CONFIGURATION_URL_BY_TAG, versionTag); JSONObject responseJSON = readFromCluster(url); @@ -398,7 +362,6 @@ public class ConfigurationService { public Response writeConfiguration(JSONObject request) { JSONObject response; try { - validateViewConfiguration(); if (isOperator() == false) { return Response.status(401).build(); @@ -467,7 +430,7 @@ public class ConfigurationService { String rmHosts = getRMHosts(); JSONObject data = getJsonObject(String.format(RESTART_RM_REQUEST_DATA, - ambariApi.getCluster().getName(), rmHosts, rmHosts)); + context.getCluster().getName(), rmHosts, rmHosts)); Map<String, String> headers = new HashMap<String, String>(); headers.put("Content-Type", "application/x-www-form-urlencoded"); @@ -491,7 +454,7 @@ public class ConfigurationService { @Path("/getConfig") public Response getConfigurationValue(@QueryParam("siteName") String siteName,@QueryParam("configName") String configName){ try{ - String configValue = ambariApi.getCluster().getConfigurationValue(siteName,configName); + String configValue = context.getCluster().getConfigurationValue(siteName,configName); JSONObject res = new JSONObject(); JSONArray arr = new JSONArray(); JSONObject conf = new JSONObject(); http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/capacity-scheduler/src/main/resources/view.xml ---------------------------------------------------------------------- diff --git a/contrib/views/capacity-scheduler/src/main/resources/view.xml b/contrib/views/capacity-scheduler/src/main/resources/view.xml index 6dc3ffa..bd07a3f 100644 --- a/contrib/views/capacity-scheduler/src/main/resources/view.xml +++ b/contrib/views/capacity-scheduler/src/main/resources/view.xml @@ -24,30 +24,7 @@ <validator-class>org.apache.ambari.view.capacityscheduler.PropertyValidator</validator-class> - <parameter> - <name>ambari.server.url</name> - <description>Enter the Ambari Server REST API cluster resource.</description> - <label>Ambari Cluster URL</label> - <placeholder>http://ambari.server:8080/api/v1/clusters/MyCluster</placeholder> - <cluster-config>fake</cluster-config> - <required>true</required> - </parameter> - <parameter> - <name>ambari.server.username</name> - <description>Enter the Cluster Operator username (for example: admin).</description> - <label>Operator Username</label> - <placeholder>admin</placeholder> - <cluster-config>fake</cluster-config> - <required>true</required> - </parameter> - <parameter> - <name>ambari.server.password</name> - <description>Enter the Cluster Operator password (for example: password).</description> - <label>Operator Password</label> - <cluster-config>fake</cluster-config> - <required>true</required> - <masked>true</masked> - </parameter> + <cluster-config-options>AMBARI-ONLY</cluster-config-options> <resource> <name>scheduler</name> http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/capacity-scheduler/src/test/java/org/apache/ambari/view/capacityscheduler/ConfigurationServiceTest.java ---------------------------------------------------------------------- diff --git a/contrib/views/capacity-scheduler/src/test/java/org/apache/ambari/view/capacityscheduler/ConfigurationServiceTest.java b/contrib/views/capacity-scheduler/src/test/java/org/apache/ambari/view/capacityscheduler/ConfigurationServiceTest.java index 62fa21e..add0d0f 100644 --- a/contrib/views/capacity-scheduler/src/test/java/org/apache/ambari/view/capacityscheduler/ConfigurationServiceTest.java +++ b/contrib/views/capacity-scheduler/src/test/java/org/apache/ambari/view/capacityscheduler/ConfigurationServiceTest.java @@ -57,11 +57,6 @@ public class ConfigurationServiceTest { httpHeaders = createNiceMock(HttpHeaders.class); ambariCluster = createNiceMock(Cluster.class); - properties = new HashMap<String, String>(); - properties.put(AmbariApi.AMBARI_SERVER_URL_INSTANCE_PROPERTY, BASE_URI); - properties.put(AmbariApi.AMBARI_SERVER_USERNAME_INSTANCE_PROPERTY, "admin"); - properties.put(AmbariApi.AMBARI_SERVER_PASSWORD_INSTANCE_PROPERTY, "admin"); - EasyMock.expect(ambariCluster.getConfigurationValue("ranger-yarn-plugin-properties", "ranger-yarn-plugin-enabled")).andReturn("Yes").anyTimes(); EasyMock.expect(context.getCluster()).andReturn(ambariCluster).anyTimes(); EasyMock.expect(context.getProperties()).andReturn(properties).anyTimes(); http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/hive/src/main/java/org/apache/ambari/view/hive/resources/uploads/UploadService.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive/src/main/java/org/apache/ambari/view/hive/resources/uploads/UploadService.java b/contrib/views/hive/src/main/java/org/apache/ambari/view/hive/resources/uploads/UploadService.java index 83eae9b..4afe80b 100644 --- a/contrib/views/hive/src/main/java/org/apache/ambari/view/hive/resources/uploads/UploadService.java +++ b/contrib/views/hive/src/main/java/org/apache/ambari/view/hive/resources/uploads/UploadService.java @@ -329,7 +329,7 @@ public class UploadService extends BaseService { } private String getHiveMetaStoreLocation() { - String dir = this.getAmbariApi().getProperty(HIVE_SITE,HIVE_METASTORE_LOCATION_KEY,HIVE_METASTORE_LOCATION_KEY_VIEW_PROPERTY); + String dir = context.getProperties().get(HIVE_METASTORE_LOCATION_KEY_VIEW_PROPERTY); if(dir != null && !dir.trim().isEmpty()){ return dir; }else{ http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/BaseHttpClient.java ---------------------------------------------------------------------- diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/BaseHttpClient.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/BaseHttpClient.java index b4fccf9..3d4a08d 100644 --- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/BaseHttpClient.java +++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/BaseHttpClient.java @@ -27,7 +27,6 @@ import java.util.Map; import org.apache.ambari.view.URLStreamProvider; import org.apache.ambari.view.ViewContext; import org.apache.ambari.view.utils.ambari.AmbariApi; -import org.apache.ambari.view.utils.ambari.URLStreamProviderBasicAuth; import org.apache.commons.httpclient.HttpException; import org.apache.commons.io.IOUtils; @@ -76,10 +75,6 @@ public class BaseHttpClient { return viewContext.getURLStreamProvider(); } - public URLStreamProviderBasicAuth getUrlStreamProviderBasicAuth() { - return ambariApi.getUrlStreamProviderBasicAuth(); - } - public String getUrl() { return url; } @@ -118,42 +113,39 @@ public class BaseHttpClient { public JsonElement doGetJson(String url, String path) throws HttpException, IOException { - InputStream inputStream = null; + String response = null; try { Map<String, String> headers = new HashMap<String, String>(); if (isNeedsAuthentication()) { - inputStream = getUrlStreamProviderBasicAuth().readFrom( + response = ambariApi.readFromAmbari( url + path, "GET", (String) null, headers); } else { - inputStream = getUrlStreamProviderBasicAuth().readAsCurrent( - url + path, "GET", (String) null, headers); + response = IOUtils.toString(viewContext.getURLStreamProvider().readAsCurrent( + url + path, "GET", (String) null, headers)); } - } catch (IOException e) { + } catch (Exception e) { logger.error("Error while reading from url " + url + path, e); HttpException httpException = new HttpException( e.getLocalizedMessage()); throw httpException; } - JsonElement jsonElement = new JsonParser().parse(new JsonReader( - new InputStreamReader(inputStream))); + JsonElement jsonElement = new JsonParser().parse(response); return jsonElement; } public String doGet(String path) throws HttpException, IOException { String response = null; try { - InputStream inputStream = null; if (isNeedsAuthentication()) { - inputStream = getUrlStreamProviderBasicAuth().readFrom( + response = ambariApi.readFromAmbari( getUrl() + path, "GET", (String) null, new HashMap<String, String>()); } else { - inputStream = getUrlStreamProviderBasicAuth().readAsCurrent( + response = IOUtils.toString(viewContext.getURLStreamProvider().readAsCurrent( getUrl() + path, "GET", (String) null, - new HashMap<String, String>()); + new HashMap<String, String>())); } - response = IOUtils.toString(inputStream); - } catch (IOException e) { + } catch (Exception e) { logger.error("Error while reading from url " + getUrl() + path, e); HttpException httpException = new HttpException( e.getLocalizedMessage()); http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/AmbariApi.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/AmbariApi.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/AmbariApi.java index 6b88b6f..6072d28 100644 --- a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/AmbariApi.java +++ b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/AmbariApi.java @@ -18,6 +18,7 @@ package org.apache.ambari.view.utils.ambari; +import org.apache.ambari.view.AmbariHttpException; import org.apache.ambari.view.URLStreamProvider; import org.apache.ambari.view.ViewContext; import org.apache.ambari.view.cluster.Cluster; @@ -31,6 +32,7 @@ import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,54 +42,31 @@ import java.util.Map; * on both local and remote cluster. */ public class AmbariApi { - public static final String AMBARI_SERVER_URL_INSTANCE_PROPERTY = "ambari.server.url"; - public static final String AMBARI_SERVER_USERNAME_INSTANCE_PROPERTY = "ambari.server.username"; - public static final String AMBARI_SERVER_PASSWORD_INSTANCE_PROPERTY = "ambari.server.password"; - private Cluster cluster; private ViewContext context; private Services services; - private String remoteUrlCluster; - private String remoteUsername; - private String remotePassword; private String requestedBy = "views"; + public static String API_PREFIX = "/api/v1/clusters/"; + /** * Constructor for Ambari API based on ViewContext * @param context View Context */ public AmbariApi(ViewContext context) { this.context = context; - - remoteUrlCluster = context.getProperties().get(AMBARI_SERVER_URL_INSTANCE_PROPERTY); - remoteUsername = context.getProperties().get(AMBARI_SERVER_USERNAME_INSTANCE_PROPERTY); - remotePassword = context.getProperties().get(AMBARI_SERVER_PASSWORD_INSTANCE_PROPERTY); } /** - * X-Requested-By header value - * @param requestedBy value of X-Requested-By header + * Set requestedBy header + * + * @param requestedBy */ public void setRequestedBy(String requestedBy) { this.requestedBy = requestedBy; } - private String parseAmbariHostname(String remoteUrlCluster) { - String hostname; - try { - URI uri = new URI(remoteUrlCluster); - hostname = String.format("%s://%s", uri.getScheme(), uri.getHost()); - if (uri.getPort() != -1) { - hostname += ":" + uri.getPort(); - } - } catch (URISyntaxException e) { - throw new AmbariApiException("RA060 Malformed URI of remote Ambari"); - } - - return hostname; - } - /** * Provides ability to get cluster topology * @param requestComponent name of component @@ -153,27 +132,24 @@ public class AmbariApi { */ public String requestClusterAPI(String path, String method, String data, Map<String, String> headers) throws AmbariApiException { String response; - URLStreamProviderBasicAuth urlStreamProvider = getUrlStreamProviderBasicAuth(); try { - String url; - if (isLocalCluster()) { - url = String.format("/api/v1/clusters/%s/%s", getCluster().getName(), path); - - } else if (isRemoteCluster()) { - - url = String.format("%s/%s", remoteUrlCluster, path); - - } else { + if (context.getAmbariClusterStreamProvider() == null || context.getCluster() == null) { throw new NoClusterAssociatedException( "RA030 View is not associated with any cluster. No way to request Ambari."); } - InputStream inputStream = urlStreamProvider.readFrom(url, method, data, headers); + if(!path.startsWith("/")) path = "/" + path; + + path = API_PREFIX + context.getCluster().getName() + path; + + InputStream inputStream = context.getAmbariClusterStreamProvider().readFrom(path, method, data, addRequestedByHeader(headers)); response = IOUtils.toString(inputStream); } catch (IOException e) { throw new AmbariApiException("RA040 I/O error while requesting Ambari", e); + } catch (AmbariHttpException e) { + throw new AmbariApiException("RA040 Request to Ambari is unsuccessful with response code "+e.getResponseCode(), e); } return response; } @@ -189,118 +165,25 @@ public class AmbariApi { */ public String readFromAmbari(String path, String method, String data, Map<String, String> headers) throws AmbariApiException { String response; - URLStreamProviderBasicAuth urlStreamProvider = getUrlStreamProviderBasicAuth(); try { - String url; - - if (isLocalCluster()) { - url = path; - - } else if (isRemoteCluster()) { - String ambariUrl = parseAmbariHostname(remoteUrlCluster); - url = ambariUrl + path; - } else { + if (context.getAmbariClusterStreamProvider() == null) { throw new NoClusterAssociatedException( "RA060 View is not associated with any cluster. No way to request Ambari."); } - InputStream inputStream = urlStreamProvider.readFrom(url, method, data, headers); + InputStream inputStream = context.getAmbariClusterStreamProvider().readFrom(path, method, data, addRequestedByHeader(headers)); response = IOUtils.toString(inputStream); } catch (IOException e) { throw new AmbariApiException("RA050 I/O error while requesting Ambari", e); + } catch (AmbariHttpException e) { + throw new AmbariApiException("RA040 Request to Ambari is unsuccessful with response code "+e.getResponseCode(), e); } return response; } - /** - * Check if associated with local or remote cluster - * @return true if associated - */ - public boolean isClusterAssociated() { - try { - getCluster(); - return true; - } catch (NoClusterAssociatedException e) { - return false; - } - } - - /** - * Cluster object that provides access for Ambari configuration - * @return cluster if locally associated or RemoteCluster - * @throws NoClusterAssociatedException - */ - public Cluster getCluster() throws NoClusterAssociatedException { - if (cluster == null) { - if (isLocalCluster()) { - cluster = context.getCluster(); - - } else if (isRemoteCluster()) { - cluster = getRemoteCluster(); - - } else { - throw new NoClusterAssociatedException( - "RA050 View is not associated with any cluster. No way to request Ambari."); - } - } - return cluster; - } - - /** - * Is associated with local cluster - * @return true if associated - */ - public boolean isLocalCluster() { - return context.getCluster() != null; - } - - /** - * Is associated with remote cluster - * @return true if associated - */ - public boolean isRemoteCluster() { - return remoteUrlCluster != null && !remoteUrlCluster.isEmpty(); - } - - /** - * Build RemoteCluster instance based on viewContext properties - * @return RemoteCluster instance - */ - public RemoteCluster getRemoteCluster() { - if (!isRemoteCluster()) - return null; - - URLStreamProvider urlStreamProviderBasicAuth = getUrlStreamProviderBasicAuth(); - return new RemoteCluster(remoteUrlCluster, urlStreamProviderBasicAuth); - } - - /** - * Build URLStreamProvider with Basic Authentication for Remote Cluster - * @return URLStreamProvider - */ - public URLStreamProviderBasicAuth getUrlStreamProviderBasicAuth() { - URLStreamProviderBasicAuth urlStreamProviderBasicAuth; - if (isRemoteCluster()) { - if (remoteUsername == null || remoteUsername.isEmpty() || - remotePassword == null || remotePassword.isEmpty()) { - throw new AmbariApiException("RA020 Remote Ambari username and password are not filled"); - } - - URLStreamProvider urlStreamProvider = context.getURLStreamProvider(); - urlStreamProviderBasicAuth = - new URLStreamProviderBasicAuth(urlStreamProvider, remoteUsername, remotePassword); - } else if (isLocalCluster()) { - urlStreamProviderBasicAuth = new URLStreamProviderBasicAuth(context.getAmbariStreamProvider()); - } else { - throw new NoClusterAssociatedException( - "RA070 Not associated with any cluster. URLStreamProvider is not available"); - } - urlStreamProviderBasicAuth.setRequestedBy(requestedBy); - return urlStreamProviderBasicAuth; - } /** * Provides access to service-specific utilities @@ -313,11 +196,23 @@ public class AmbariApi { return services; } - public String getProperty(String type, String key, String instanceProperty) { - try { - return this.getCluster().getConfigurationValue(type, key); - } catch (NoClusterAssociatedException e) { - return context.getProperties().get(instanceProperty); + private Map<String,String> addRequestedByHeader(Map<String,String> headers){ + if(headers == null){ + headers = new HashMap<String, String>(); } + + headers.put("X-Requested-By",this.requestedBy); + + return headers; } + + /** + * Check if view is associated with cluster + * + * @return isClusterAssociated + */ + public boolean isClusterAssociated(){ + return context.getCluster() != null; + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/RemoteCluster.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/RemoteCluster.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/RemoteCluster.java deleted file mode 100644 index 41dc88d..0000000 --- a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/RemoteCluster.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * 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.view.utils.ambari; - -import org.apache.ambari.view.URLStreamProvider; -import org.apache.ambari.view.ViewContext; -import org.apache.ambari.view.cluster.Cluster; -import org.apache.commons.collections4.map.PassiveExpiringMap; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.input.NullInputStream; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Collections; -import java.util.Map; - -/** - * Class that provides same interface as local Cluster, but - * is able to retrieve configuration values by REST API - */ -public class RemoteCluster implements Cluster { - protected String name; - protected String baseUrl; - protected URLStreamProvider urlStreamProvider; - protected Map<String, JSONObject> configurationCache; - - /** - * Constructor for RemoteCluster - * @param ambariClusterUrl Ambari Server Cluster REST API URL (for example: http://ambari.server:8080/api/v1/clusters/c1) - * @param urlStreamProvider stream provider with authorization support - */ - public RemoteCluster(String ambariClusterUrl, URLStreamProvider urlStreamProvider) { - this.baseUrl = ambariClusterUrl; - this.urlStreamProvider = urlStreamProvider; - - String[] parts = ambariClusterUrl.split("/"); - this.name = parts[parts.length-1]; - PassiveExpiringMap<String, JSONObject> configurations = new PassiveExpiringMap<String, JSONObject>(10000L); // keep cache for 10 seconds - configurationCache = Collections.synchronizedMap(configurations); - } - - @Override - public String getName() { - return name; - } - - @Override - public String getConfigurationValue(String type, String key) { - JSONObject config; - try { - String desiredTag = getDesiredConfig(type); - config = readFromUrlJSON(String.format("%s/configurations?(type=%s&tag=%s)", baseUrl, type, desiredTag)); - } catch (IOException e) { - throw new AmbariApiException("RA010 Can't retrieve configuration from Remote Ambari", e); - } - - JSONObject items = (JSONObject) ((JSONArray) config.get("items")).get(0); - JSONObject properties = (JSONObject) items.get("properties"); - return (properties == null ? null : (String) properties.get(key)); - } - - private String getDesiredConfig(String type) throws IOException { - JSONObject desiredConfigResponse = readFromUrlJSON( - String.format("%s?fields=services/ServiceInfo,hosts,Clusters", baseUrl)); - JSONObject clusters = (JSONObject) (desiredConfigResponse.get("Clusters")); - JSONObject desiredConfig = (JSONObject) (clusters.get("desired_configs")); - JSONObject desiredConfigForType = (JSONObject) desiredConfig.get(type); - - return (String) desiredConfigForType.get("tag"); - } - - private JSONObject readFromUrlJSON(String url) throws IOException { - JSONObject jsonObject = configurationCache.get(url); - if (jsonObject == null) { - InputStream inputStream = urlStreamProvider.readFrom(url, "GET", (String)null, null); - String response = IOUtils.toString(inputStream); - jsonObject = (JSONObject) JSONValue.parse(response); - - configurationCache.put(url, jsonObject); - } - return jsonObject; - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/Services.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/Services.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/Services.java index a8ef43f..1bace94 100644 --- a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/Services.java +++ b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/Services.java @@ -75,7 +75,7 @@ public class Services { public String getRMUrl() { String url; - if (ambariApi.isClusterAssociated()) { + if (context.getCluster() != null) { url = getRMUrlFromClusterConfig(); } else { url = getRmUrlFromCustomConfig(); @@ -216,7 +216,7 @@ public class Services { public String getWebHCatURL() { String host = null; - if (ambariApi.isClusterAssociated()) { + if (context.getCluster() != null) { List<String> hiveServerHosts = ambariApi.getHostsWithComponent("WEBHCAT_SERVER"); if (!hiveServerHosts.isEmpty()) { @@ -249,7 +249,7 @@ public class Services { * yarn-site.xml else it is retrieved from the view configuration. */ public String getTimelineServerUrl() { - String url = ambariApi.isClusterAssociated() ? getATSUrlFromCluster() : getATSUrlFromCustom(); + String url = context.getCluster() != null ? getATSUrlFromCluster() : getATSUrlFromCustom(); return removeTrailingSlash(url); } @@ -337,7 +337,7 @@ public class Services { } private String getYarnConfig(String key) { - return ambariApi.getCluster().getConfigurationValue(YARN_SITE, key); + return context.getCluster().getConfigurationValue(YARN_SITE, key); } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/c150f0de/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/URLStreamProviderBasicAuth.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/URLStreamProviderBasicAuth.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/URLStreamProviderBasicAuth.java deleted file mode 100644 index c9f735a..0000000 --- a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/ambari/URLStreamProviderBasicAuth.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * 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.view.utils.ambari; - -import org.apache.ambari.view.AmbariStreamProvider; -import org.apache.ambari.view.URLStreamProvider; -import org.apache.commons.codec.binary.Base64; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -/** - * Wrapper for URLStreamProvider that adds authentication header. - * Also supports AmbariStreamProvider. readAs or readAsCurrent should not be used - * with AmbariStreamProvider. - */ -public class URLStreamProviderBasicAuth implements URLStreamProvider { - private URLStreamProvider urlStreamProvider; - private AmbariStreamProvider ambariStreamProvider; - private String username; - private String password; - private String requestedBy = "views"; - - public URLStreamProviderBasicAuth(URLStreamProvider urlStreamProvider, String username, String password) { - this.urlStreamProvider = urlStreamProvider; - this.username = username; - this.password = password; - } - - public URLStreamProviderBasicAuth(AmbariStreamProvider urlStreamProvider) { - this.ambariStreamProvider = urlStreamProvider; - } - - /** - * X-Requested-By header value - * @param requestedBy value of X-Requested-By header - */ - public void setRequestedBy(String requestedBy) { - this.requestedBy = requestedBy; - } - - @Override - public InputStream readFrom(String url, String method, String data, Map<String, String> headers) throws IOException { - if (urlStreamProvider != null) { - return urlStreamProvider.readFrom(url, method, data, addHeaders(headers)); - } else { - return ambariStreamProvider.readFrom(url, method, data, addHeaders(headers), true); - } - } - - @Override - public InputStream readFrom(String url, String method, InputStream data, Map<String, String> headers) throws IOException { - if (urlStreamProvider != null) { - return urlStreamProvider.readFrom(url, method, data, addHeaders(headers)); - } else { - return ambariStreamProvider.readFrom(url, method, data, addHeaders(headers), true); - } - } - - @Override - public InputStream readAs(String url, String method, String data, Map<String, String> headers, String doAs) throws IOException { - return urlStreamProvider.readAs(url, method, data, addHeaders(headers), doAs); - } - - @Override - public InputStream readAs(String url, String method, InputStream data, Map<String, String> headers, String doAs) throws IOException { - return urlStreamProvider.readAs(url, method, data, addHeaders(headers), doAs); - } - - @Override - public InputStream readAsCurrent(String url, String method, String data, Map<String, String> headers) throws IOException { - return urlStreamProvider.readAsCurrent(url, method, data, addHeaders(headers)); - } - - @Override - public InputStream readAsCurrent(String url, String method, InputStream data, Map<String, String> headers) throws IOException { - return urlStreamProvider.readAsCurrent(url, method, data, addHeaders(headers)); - } - - private HashMap<String, String> addHeaders(Map<String, String> customHeaders) { - HashMap<String, String> newHeaders = new HashMap<String, String>(); - if (customHeaders != null) - newHeaders.putAll(customHeaders); - - if (urlStreamProvider != null) { - // basic auth is not needed for AmbariStreamProvider - addBasicAuthHeaders(newHeaders); - } - addRequestedByHeaders(newHeaders); - return newHeaders; - } - - private void addRequestedByHeaders(HashMap<String, String> newHeaders) { - newHeaders.put("X-Requested-By", requestedBy); - } - - private void addBasicAuthHeaders(HashMap<String, String> headers) { - String authString = username + ":" + password; - byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); - String authStringEnc = new String(authEncBytes); - - headers.put("Authorization", "Basic " + authStringEnc); - } -}
