You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2014/07/01 22:42:03 UTC
[1/2] AMBARI-6343. Views : Admin - Add Group and Group Member
Resources.
Repository: ambari
Updated Branches:
refs/heads/trunk 01e9e7607 -> 00a4991ee
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
new file mode 100644
index 0000000..b4e015d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
@@ -0,0 +1,70 @@
+/**
+ * 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.orm.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+@Singleton
+public class MemberDAO {
+ @Inject
+ Provider<EntityManager> entityManagerProvider;
+ @Inject
+ DaoUtils daoUtils;
+
+ @RequiresSession
+ public MemberEntity findByPK(Integer memberPK) {
+ return entityManagerProvider.get().find(MemberEntity.class, memberPK);
+ }
+
+ @RequiresSession
+ public List<MemberEntity> findAll() {
+ final TypedQuery<MemberEntity> query = entityManagerProvider.get().createQuery("SELECT member FROM MemberEntity member", MemberEntity.class);
+ return daoUtils.selectList(query);
+ }
+
+ @Transactional
+ public void create(MemberEntity member) {
+ entityManagerProvider.get().persist(member);
+ }
+
+ @Transactional
+ public MemberEntity merge(MemberEntity member) {
+ return entityManagerProvider.get().merge(member);
+ }
+
+ @Transactional
+ public void remove(MemberEntity member) {
+ entityManagerProvider.get().remove(merge(member));
+ }
+
+ @Transactional
+ public void removeByPK(Integer memberPK) {
+ remove(findByPK(memberPK));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/GroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/GroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/GroupEntity.java
new file mode 100644
index 0000000..64fcf9a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/GroupEntity.java
@@ -0,0 +1,120 @@
+/**
+ * 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.orm.entities;
+
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+@Entity
+@Table(name = "groups", uniqueConstraints = {@UniqueConstraint(columnNames = {"group_name", "ldap_group"})})
+@TableGenerator(name = "group_id_generator",
+ table = "ambari_sequences",
+ pkColumnName = "sequence_name",
+ valueColumnName = "value",
+ pkColumnValue = "group_id_seq",
+ initialValue = 1,
+ allocationSize = 1
+ )
+@NamedQueries({
+ @NamedQuery(name = "groupByName", query = "SELECT group_entity FROM GroupEntity group_entity where lower(group_entity.groupName)=:groupname")
+})
+public class GroupEntity {
+ @Id
+ @Column(name = "group_id")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "group_id_generator")
+ private Integer groupId;
+
+ @Column(name = "group_name")
+ private String groupName;
+
+ @Column(name = "ldap_group")
+ private Integer ldapGroup = 0;
+
+ @OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
+ private Set<MemberEntity> memberEntities;
+
+ public Integer getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(Integer groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public Boolean getLdapGroup() {
+ return ldapGroup == 0 ? Boolean.FALSE : Boolean.TRUE;
+ }
+
+ public void setLdapGroup(Boolean ldapGroup) {
+ if (ldapGroup == null) {
+ this.ldapGroup = null;
+ } else {
+ this.ldapGroup = ldapGroup ? 1 : 0;
+ }
+ }
+
+ public Set<MemberEntity> getMemberEntities() {
+ return memberEntities;
+ }
+
+ public void setMemberEntities(Set<MemberEntity> memberEntities) {
+ this.memberEntities = memberEntities;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ GroupEntity that = (GroupEntity) o;
+
+ if (groupId != null ? !groupId.equals(that.groupId) : that.groupId != null) return false;
+ if (groupName != null ? !groupName.equals(that.groupName) : that.groupName != null) return false;
+ if (ldapGroup != null ? !ldapGroup.equals(that.ldapGroup) : that.ldapGroup != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = groupId != null ? groupId.hashCode() : 0;
+ result = 31 * result + (groupName != null ? groupName.hashCode() : 0);
+ result = 31 * result + (ldapGroup != null ? ldapGroup.hashCode() : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MemberEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MemberEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MemberEntity.java
new file mode 100644
index 0000000..04b1a87
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/MemberEntity.java
@@ -0,0 +1,100 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+@Entity
+@Table(name = "members", uniqueConstraints = {@UniqueConstraint(columnNames = {"group_id", "user_id"})})
+@TableGenerator(name = "member_id_generator",
+ table = "ambari_sequences",
+ pkColumnName = "sequence_name",
+ valueColumnName = "value",
+ pkColumnValue = "member_id_seq",
+ initialValue = 1,
+ allocationSize = 1
+ )
+public class MemberEntity {
+ @Id
+ @Column(name = "member_id")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "member_id_generator")
+ private Integer memberId;
+
+ @ManyToOne
+ @JoinColumn(name = "group_id")
+ private GroupEntity group;
+
+ @ManyToOne
+ @JoinColumn(name = "user_id")
+ private UserEntity user;
+
+ public Integer getMemberId() {
+ return memberId;
+ }
+
+ public void setMemberId(Integer memberId) {
+ this.memberId = memberId;
+ }
+
+ public GroupEntity getGroup() {
+ return group;
+ }
+
+ public void setGroup(GroupEntity group) {
+ this.group = group;
+ }
+
+ public UserEntity getUser() {
+ return user;
+ }
+
+ public void setUser(UserEntity user) {
+ this.user = user;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MemberEntity that = (MemberEntity) o;
+
+ if (memberId != null ? !memberId.equals(that.memberId) : that.memberId != null) return false;
+ if (group != null ? !group.equals(that.group) : that.group != null) return false;
+ if (user != null ? !user.equals(that.user) : that.user != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = memberId != null ? memberId.hashCode() : 0;
+ result = 31 * result + (group != null ? group.hashCode() : 0);
+ result = 31 * result + (user != null ? user.hashCode() : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
index 1dc9e9f..14ad304 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserEntity.java
@@ -59,6 +59,9 @@ public class UserEntity {
@ManyToMany(mappedBy = "userEntities")
private Set<RoleEntity> roleEntities;
+ @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
+ private Set<MemberEntity> memberEntities;
+
public Integer getUserId() {
return userId;
}
@@ -103,6 +106,22 @@ public class UserEntity {
this.createTime = createTime;
}
+ public Set<RoleEntity> getRoleEntities() {
+ return roleEntities;
+ }
+
+ public void setRoleEntities(Set<RoleEntity> roleEntities) {
+ this.roleEntities = roleEntities;
+ }
+
+ public Set<MemberEntity> getMemberEntities() {
+ return memberEntities;
+ }
+
+ public void setMemberEntities(Set<MemberEntity> memberEntities) {
+ this.memberEntities = memberEntities;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -128,12 +147,4 @@ public class UserEntity {
result = 31 * result + (createTime != null ? createTime.hashCode() : 0);
return result;
}
-
- public Set<RoleEntity> getRoleEntities() {
- return roleEntities;
- }
-
- public void setRoleEntities(Set<RoleEntity> roleEntities) {
- this.roleEntities = roleEntities;
- }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Group.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Group.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Group.java
new file mode 100644
index 0000000..b20df8d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Group.java
@@ -0,0 +1,53 @@
+/*
+ * 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.security.authorization;
+
+import org.apache.ambari.server.orm.entities.GroupEntity;
+
+/**
+ * Describes group of users of web-service.
+ */
+public class Group {
+ private final int groupId;
+ private final String groupName;
+ private final boolean ldapGroup;
+
+ Group(GroupEntity groupEntity) {
+ this.groupId = groupEntity.getGroupId();
+ this.groupName = groupEntity.getGroupName();
+ this.ldapGroup = groupEntity.getLdapGroup();
+ }
+
+ public int getGroupId() {
+ return groupId;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public boolean isLdapGroup() {
+ return ldapGroup;
+ }
+
+ @Override
+ public String toString() {
+ return "Group [groupId=" + groupId + ", groupName=" + groupName
+ + ", ldapGroup=" + ldapGroup + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Member.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Member.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Member.java
new file mode 100644
index 0000000..da4732a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Member.java
@@ -0,0 +1,53 @@
+/*
+ * 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.security.authorization;
+
+import org.apache.ambari.server.orm.entities.GroupEntity;
+
+/**
+ * Describes group of users of web-service.
+ */
+public class Member {
+ private final int groupId;
+ private final String groupName;
+ private final boolean ldapGroup;
+
+ Member(GroupEntity groupEntity) {
+ this.groupId = groupEntity.getGroupId();
+ this.groupName = groupEntity.getGroupName();
+ this.ldapGroup = groupEntity.getLdapGroup();
+ }
+
+ public int getGroupId() {
+ return groupId;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public boolean isLdapGroup() {
+ return ldapGroup;
+ }
+
+ @Override
+ public String toString() {
+ return "Group [groupId=" + groupId + ", groupName=" + groupName
+ + ", ldapGroup=" + ldapGroup + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
index b4cbdf9..072d3de 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
@@ -18,13 +18,19 @@
package org.apache.ambari.server.security.authorization;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.MemberDAO;
import org.apache.ambari.server.orm.dao.RoleDAO;
import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+import org.apache.ambari.server.orm.entities.MemberEntity;
import org.apache.ambari.server.orm.entities.RoleEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
import org.slf4j.Logger;
@@ -38,7 +44,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;
-import java.util.Set;
/**
* Provides high-level access to Users and Roles in database
@@ -53,6 +58,10 @@ public class Users {
@Inject
protected RoleDAO roleDAO;
@Inject
+ protected GroupDAO groupDAO;
+ @Inject
+ protected MemberDAO memberDAO;
+ @Inject
protected PasswordEncoder passwordEncoder;
@Inject
protected Configuration configuration;
@@ -191,6 +200,72 @@ public class Users {
}
/**
+ * Gets group by given name.
+ *
+ * @param groupName group name
+ * @return group
+ */
+ public Group getGroup(String groupName) {
+ final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
+ return (null == groupEntity) ? null : new Group(groupEntity);
+ }
+
+ /**
+ * Gets group members.
+ *
+ * @param groupName group name
+ * @return list of members
+ */
+ public Collection<User> getGroupMembers(String groupName) {
+ final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
+ if (groupEntity == null) {
+ return null;
+ } else {
+ final Set<User> users = new HashSet<User>();
+ for (MemberEntity memberEntity: groupEntity.getMemberEntities()) {
+ users.add(new User(memberEntity.getUser()));
+ }
+ return users;
+ }
+ }
+
+ /**
+ * Creates new local group with provided name
+ */
+ @Transactional
+ public synchronized void createGroup(String groupName) {
+ final GroupEntity groupEntity = new GroupEntity();
+ groupEntity.setGroupName(groupName);
+ groupDAO.create(groupEntity);
+ }
+
+ /**
+ * Gets all groups.
+ *
+ * @return list of groups
+ */
+ public List<Group> getAllGroups() {
+ final List<GroupEntity> groupEntities = groupDAO.findAll();
+ final List<Group> groups = new ArrayList<Group>(groupEntities.size());
+
+ for (GroupEntity groupEntity: groupEntities) {
+ groups.add(new Group(groupEntity));
+ }
+
+ return groups;
+ }
+
+ @Transactional
+ public synchronized void removeGroup(Group group) throws AmbariException {
+ final GroupEntity groupEntity = groupDAO.findByPK(group.getGroupId());
+ if (groupEntity != null) {
+ groupDAO.remove(groupEntity);
+ } else {
+ throw new AmbariException("Group " + group + " doesn't exist");
+ }
+ }
+
+ /**
* Grants ADMIN role to provided user
* @throws AmbariException
*/
@@ -243,6 +318,37 @@ public class Users {
}
@Transactional
+ public synchronized void addMemberToGroup(String groupName, String userName)
+ throws AmbariException {
+
+ final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
+ if (groupEntity == null) {
+ throw new AmbariException("Group " + groupName + " doesn't exist");
+ }
+
+ UserEntity userEntity = userDAO.findLocalUserByName(userName);
+ if (userEntity == null) {
+ userEntity = userDAO.findLdapUserByName(userName);
+ if (userEntity == null) {
+ throw new AmbariException("User " + userName + " doesn't exist");
+ }
+ }
+
+ if (isUserInGroup(userEntity, groupEntity)) {
+ throw new AmbariException("User " + userName + " is already present in group " + groupName);
+ } else {
+ final MemberEntity memberEntity = new MemberEntity();
+ memberEntity.setGroup(groupEntity);
+ memberEntity.setUser(userEntity);
+ userEntity.getMemberEntities().add(memberEntity);
+ groupEntity.getMemberEntities().add(memberEntity);
+ memberDAO.create(memberEntity);
+ userDAO.merge(userEntity);
+ groupDAO.merge(groupEntity);
+ }
+ }
+
+ @Transactional
public synchronized void removeRoleFromUser(User user, String role)
throws AmbariException {
@@ -269,7 +375,7 @@ public class Users {
". System should have at least one user with administrator role.");
}
}
-
+
if (userEntity.getRoleEntities().contains(roleEntity)) {
userEntity.getRoleEntities().remove(roleEntity);
roleEntity.getUserEntities().remove(userEntity);
@@ -281,13 +387,65 @@ public class Users {
}
+ @Transactional
+ public synchronized void removeMemberFromGroup(String groupName, String userName)
+ throws AmbariException {
+
+ final GroupEntity groupEntity = groupDAO.findGroupByName(groupName);
+ if (groupEntity == null) {
+ throw new AmbariException("Group " + groupName + " doesn't exist");
+ }
+
+ UserEntity userEntity = userDAO.findLocalUserByName(userName);
+ if (userEntity == null) {
+ userEntity = userDAO.findLdapUserByName(userName);
+ if (userEntity == null) {
+ throw new AmbariException("User " + userName + " doesn't exist");
+ }
+ }
+
+ if (isUserInGroup(userEntity, groupEntity)) {
+ MemberEntity memberEntity = null;
+ for (MemberEntity entity: userEntity.getMemberEntities()) {
+ if (entity.getGroup().equals(groupEntity)) {
+ memberEntity = entity;
+ break;
+ }
+ }
+ userEntity.getMemberEntities().remove(memberEntity);
+ groupEntity.getMemberEntities().remove(memberEntity);
+ userDAO.merge(userEntity);
+ groupDAO.merge(groupEntity);
+ memberDAO.remove(memberEntity);
+ } else {
+ throw new AmbariException("User " + userName + " is not present in group " + groupName);
+ }
+
+ }
+
public synchronized boolean isUserCanBeRemoved(UserEntity userEntity){
RoleEntity roleEntity = new RoleEntity();
roleEntity.setRoleName(getAdminRole());
Set<UserEntity> userEntitysSet = new HashSet<UserEntity>(userDAO.findAllLocalUsersByRole(roleEntity));
return (userEntitysSet.contains(userEntity) && userEntitysSet.size() < 2) ? false : true;
- }
-
+ }
+
+ /**
+ * Performs a check if given user belongs to given group.
+ *
+ * @param userEntity user entity
+ * @param groupEntity group entity
+ * @return true if user presents in group
+ */
+ private boolean isUserInGroup(UserEntity userEntity, GroupEntity groupEntity) {
+ for (MemberEntity memberEntity: userEntity.getMemberEntities()) {
+ if (memberEntity.getGroup().equals(groupEntity)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public String getUserRole() {
return configuration.getConfigsMap().get(Configuration.USER_ROLE_NAME_KEY);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 f12c5d1..4821e91 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -38,6 +38,8 @@ CREATE TABLE servicecomponentdesiredstate (component_name VARCHAR(255) NOT NULL,
CREATE TABLE servicedesiredstate (cluster_id BIGINT NOT NULL, desired_host_role_mapping INTEGER NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, maintenance_state VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', PRIMARY KEY (cluster_id, service_name));
CREATE TABLE roles (role_name VARCHAR(255) NOT NULL, PRIMARY KEY (role_name));
CREATE TABLE users (user_id INTEGER, create_time TIMESTAMP DEFAULT NOW(), ldap_user INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL, user_password VARCHAR(255), PRIMARY KEY (user_id));
+CREATE TABLE groups (group_id INTEGER, group_name VARCHAR(255) NOT NULL, ldap_group INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (group_id));
+CREATE TABLE members (member_id INTEGER, group_id INTEGER NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (member_id));
CREATE TABLE execution_command (task_id BIGINT NOT NULL, command LONGBLOB, PRIMARY KEY (task_id));
CREATE TABLE host_role_command (task_id BIGINT NOT NULL, attempt_count SMALLINT NOT NULL, event LONGTEXT NOT NULL, exitcode INTEGER NOT NULL, host_name VARCHAR(255) NOT NULL, last_attempt_time BIGINT NOT NULL, request_id BIGINT NOT NULL, role VARCHAR(255), role_command VARCHAR(255), stage_id BIGINT NOT NULL, start_time BIGINT NOT NULL, end_time BIGINT, status VARCHAR(255), std_error LONGBLOB, std_out LONGBLOB, structured_out LONGBLOB, command_detail VARCHAR(255), custom_command_name VARCHAR(255), PRIMARY KEY (task_id));
CREATE TABLE role_success_criteria (role VARCHAR(255) NOT NULL, request_id BIGINT NOT NULL, stage_id BIGINT NOT NULL, success_factor DOUBLE NOT NULL, PRIMARY KEY (role, request_id, stage_id));
@@ -71,6 +73,10 @@ CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NO
CREATE TABLE viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id));
ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
+ALTER TABLE groups ADD CONSTRAINT UNQ_groups_0 UNIQUE (group_name, ldap_group);
+ALTER TABLE members ADD CONSTRAINT UNQ_members_0 UNIQUE (group_id, user_id);
+ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
+ALTER TABLE members ADD CONSTRAINT FK_members_user_id FOREIGN KEY (user_id) REFERENCES users (user_id);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -119,6 +125,8 @@ ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_
INSERT INTO ambari_sequences(sequence_name, value) values ('cluster_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('host_role_command_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('user_id_seq', 2);
+INSERT INTO ambari_sequences(sequence_name, value) values ('group_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, value) values ('member_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('configgroup_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('requestschedule_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('resourcefilter_id_seq', 1);
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 3620788..be2477b 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -28,6 +28,8 @@ CREATE TABLE servicecomponentdesiredstate (component_name VARCHAR2(255) NOT NULL
CREATE TABLE servicedesiredstate (cluster_id NUMBER(19) NOT NULL, desired_host_role_mapping NUMBER(10) NOT NULL, desired_stack_version VARCHAR2(255) NULL, desired_state VARCHAR2(255) NOT NULL, service_name VARCHAR2(255) NOT NULL, maintenance_state VARCHAR2(32) NOT NULL, PRIMARY KEY (cluster_id, service_name));
CREATE TABLE roles (role_name VARCHAR2(255) NOT NULL, PRIMARY KEY (role_name));
CREATE TABLE users (user_id NUMBER(10) NOT NULL, create_time TIMESTAMP NULL, ldap_user NUMBER(10) DEFAULT 0, user_name VARCHAR2(255) NULL, user_password VARCHAR2(255) NULL, PRIMARY KEY (user_id));
+CREATE TABLE groups (group_id NUMBER(10) NOT NULL, group_name VARCHAR2(255) NOT NULL, ldap_group NUMBER(10) DEFAULT 0, PRIMARY KEY (group_id));
+CREATE TABLE members (member_id NUMBER(10), group_id NUMBER(10) NOT NULL, user_id NUMBER(10) NOT NULL, PRIMARY KEY (member_id));
CREATE TABLE execution_command (task_id NUMBER(19) NOT NULL, command BLOB NULL, PRIMARY KEY (task_id));
CREATE TABLE host_role_command (task_id NUMBER(19) NOT NULL, attempt_count NUMBER(5) NOT NULL, event CLOB NULL, exitcode NUMBER(10) NOT NULL, host_name VARCHAR2(255) NOT NULL, last_attempt_time NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, role VARCHAR2(255) NULL, role_command VARCHAR2(255) NULL, stage_id NUMBER(19) NOT NULL, start_time NUMBER(19) NOT NULL, end_time NUMBER(19), status VARCHAR2(255) NULL, std_error BLOB NULL, std_out BLOB NULL, structured_out BLOB NULL, command_detail VARCHAR2(255) NULL, custom_command_name VARCHAR2(255) NULL, PRIMARY KEY (task_id));
CREATE TABLE role_success_criteria (role VARCHAR2(255) NOT NULL, request_id NUMBER(19) NOT NULL, stage_id NUMBER(19) NOT NULL, success_factor NUMBER(19,4) NOT NULL, PRIMARY KEY (role, request_id, stage_id));
@@ -61,6 +63,10 @@ CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NO
CREATE TABLE viewentity (id NUMBER(19) NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id));
ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
+ALTER TABLE groups ADD CONSTRAINT UNQ_groups_0 UNIQUE (group_name, ldap_group);
+ALTER TABLE members ADD CONSTRAINT UNQ_members_0 UNIQUE (group_id, user_id);
+ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
+ALTER TABLE members ADD CONSTRAINT FK_members_user_id FOREIGN KEY (user_id) REFERENCES users (user_id);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -107,6 +113,8 @@ ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_
INSERT INTO ambari_sequences(sequence_name, value) values ('host_role_command_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, value) values ('user_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, value) values ('group_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, value) values ('member_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, value) values ('cluster_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, value) values ('configgroup_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('requestschedule_id_seq', 1);
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 8c1cf3b..d964d01 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -43,6 +43,10 @@ CREATE TABLE roles (role_name VARCHAR(255) NOT NULL, PRIMARY KEY (role_name));
CREATE TABLE users (user_id INTEGER, ldap_user INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL, create_time TIMESTAMP DEFAULT NOW(), user_password VARCHAR(255), PRIMARY KEY (user_id), UNIQUE (ldap_user, user_name));
+CREATE TABLE groups (group_id INTEGER, group_name VARCHAR(255) NOT NULL, ldap_group INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (group_id), UNIQUE (ldap_group, group_name));
+
+CREATE TABLE members (member_id INTEGER, group_id INTEGER NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (member_id), UNIQUE(group_id, user_id));
+
CREATE TABLE execution_command (command BYTEA, task_id BIGINT NOT NULL, PRIMARY KEY (task_id));
CREATE TABLE host_role_command (task_id BIGINT NOT NULL, attempt_count SMALLINT NOT NULL, event VARCHAR(32000) NOT NULL, exitcode INTEGER NOT NULL, host_name VARCHAR(255) NOT NULL, last_attempt_time BIGINT NOT NULL, request_id BIGINT NOT NULL, role VARCHAR(255), stage_id BIGINT NOT NULL, start_time BIGINT NOT NULL, end_time BIGINT, status VARCHAR(255), std_error BYTEA, std_out BYTEA, structured_out BYTEA, role_command VARCHAR(255), command_detail VARCHAR(255), custom_command_name VARCHAR(255), PRIMARY KEY (task_id));
@@ -94,6 +98,8 @@ CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NO
CREATE TABLE viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id));
--------altering tables by creating foreign keys----------
+ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
+ALTER TABLE members ADD CONSTRAINT FK_members_user_id FOREIGN KEY (user_id) REFERENCES users (user_id);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -145,6 +151,10 @@ BEGIN;
UNION ALL
SELECT 'user_id_seq', 2
UNION ALL
+ SELECT 'group_id_seq', 1
+ UNION ALL
+ SELECT 'member_id_seq', 1
+ UNION ALL
SELECT 'host_role_command_id_seq', 1
union all
select 'configgroup_id_seq', 1
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 6ac6558..63f0957 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
@@ -67,6 +67,12 @@ GRANT ALL PRIVILEGES ON TABLE ambari.roles TO :username;
CREATE TABLE ambari.users (user_id INTEGER, ldap_user INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL, create_time TIMESTAMP DEFAULT NOW(), user_password VARCHAR(255), PRIMARY KEY (user_id), UNIQUE (ldap_user, user_name));
GRANT ALL PRIVILEGES ON TABLE ambari.users TO :username;
+CREATE TABLE ambari.groups (group_id INTEGER, group_name VARCHAR(255) NOT NULL, ldap_group INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (group_id), UNIQUE (ldap_group, group_name));
+GRANT ALL PRIVILEGES ON TABLE ambari.groups TO :username;
+
+CREATE TABLE ambari.members (member_id INTEGER, group_id INTEGER NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (member_id), UNIQUE(group_id, user_id));
+GRANT ALL PRIVILEGES ON TABLE ambari.members TO :username;
+
CREATE TABLE ambari.execution_command (command BYTEA, task_id BIGINT NOT NULL, PRIMARY KEY (task_id));
GRANT ALL PRIVILEGES ON TABLE ambari.execution_command TO :username;
@@ -148,6 +154,8 @@ GRANT ALL PRIVILEGES ON TABLE ambari.viewresource TO :username;
GRANT ALL PRIVILEGES ON TABLE ambari.viewentity TO :username;
--------altering tables by creating foreign keys----------
+ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
+ALTER TABLE members ADD CONSTRAINT FK_members_user_id FOREIGN KEY (user_id) REFERENCES users (user_id);
ALTER TABLE ambari.clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
ALTER TABLE ambari.clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
ALTER TABLE ambari.clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
@@ -200,6 +208,10 @@ INSERT INTO ambari.ambari_sequences (sequence_name, "value")
UNION ALL
SELECT 'user_id_seq', 2
UNION ALL
+ SELECT 'group_id_seq', 1
+ UNION ALL
+ SELECT 'member_id_seq', 1
+ UNION ALL
SELECT 'host_role_command_id_seq', 1
union all
select 'configgroup_id_seq', 1
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 9f3dcac..3026cbc 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -26,6 +26,8 @@
<class>org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity</class>
<class>org.apache.ambari.server.orm.entities.RoleEntity</class>
<class>org.apache.ambari.server.orm.entities.UserEntity</class>
+ <class>org.apache.ambari.server.orm.entities.GroupEntity</class>
+ <class>org.apache.ambari.server.orm.entities.MemberEntity</class>
<class>org.apache.ambari.server.orm.entities.ExecutionCommandEntity</class>
<class>org.apache.ambari.server.orm.entities.HostRoleCommandEntity</class>
<class>org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity</class>
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 c30a53b..68aa632 100644
--- a/ambari-server/src/main/resources/key_properties.json
+++ b/ambari-server/src/main/resources/key_properties.json
@@ -41,6 +41,13 @@
"User": {
"User": "Users/user_name"
},
+ "Group": {
+ "Group": "Groups/group_name"
+ },
+ "Member": {
+ "Group": "MemberInfo/group_name",
+ "Member": "MemberInfo/user_name"
+ },
"Stack": {
"Stack": "Stacks/stack_name"
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/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 b24aa0b..79be0e1 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -162,6 +162,16 @@
"Users/ldap_user",
"_"
],
+ "Group":[
+ "Groups/group_name",
+ "Groups/ldap_group",
+ "_"
+ ],
+ "Member":[
+ "MemberInfo/group_name",
+ "MemberInfo/user_name",
+ "_"
+ ],
"Stack":[
"Stacks/stack_name",
"_"
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/api/services/GroupServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/GroupServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/GroupServiceTest.java
new file mode 100644
index 0000000..2458920
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/GroupServiceTest.java
@@ -0,0 +1,100 @@
+/**
+ * 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.apache.ambari.server.controller.spi.Resource.Type;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for GroupService.
+ */
+public class GroupServiceTest extends BaseServiceTest {
+
+ public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+ List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+ GroupService groupService;
+ Method m;
+ Object[] args;
+
+ //getGroups
+ groupService = new TestGroupService();
+ m = groupService.getClass().getMethod("getGroups", HttpHeaders.class, UriInfo.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, groupService, m, args, null));
+
+ //getGroup
+ groupService = new TestGroupService();
+ m = groupService.getClass().getMethod("getGroup", HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo(), "groupname"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, groupService, m, args, null));
+
+ //createGroup
+ groupService = new TestGroupService();
+ m = groupService.getClass().getMethod("createGroup", String.class, HttpHeaders.class, UriInfo.class);
+ args = new Object[] {"body", getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.POST, groupService, m, args, "body"));
+
+ //createGroup
+ groupService = new TestGroupService();
+ m = groupService.getClass().getMethod("createGroup", String.class, HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {"body", getHttpHeaders(), getUriInfo(), "groupname"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.POST, groupService, m, args, "body"));
+
+ //deleteGroup
+ groupService = new TestGroupService();
+ m = groupService.getClass().getMethod("deleteGroup", HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo(), "groupname"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.DELETE, groupService, m, args, null));
+
+ return listInvocations;
+ }
+
+ private class TestGroupService extends GroupService {
+ @Override
+ ResourceInstance createResource(Type type, Map<Type, String> mapIds) {
+ return getTestResource();
+ }
+
+ @Override
+ RequestFactory getRequestFactory() {
+ return getTestRequestFactory();
+ }
+
+ @Override
+ protected RequestBodyParser getBodyParser() {
+ return getTestBodyParser();
+ }
+
+ @Override
+ protected ResultSerializer getResultSerializer() {
+ return getTestResultSerializer();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/api/services/MemberServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/MemberServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/MemberServiceTest.java
new file mode 100644
index 0000000..17b2031
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/MemberServiceTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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.apache.ambari.server.controller.spi.Resource.Type;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for GroupService.
+ */
+public class MemberServiceTest extends BaseServiceTest {
+
+ public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+ List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+ MemberService memberService;
+ Method m;
+ Object[] args;
+
+ //createMember
+ memberService = new TestMemberService("engineering");
+ m = memberService.getClass().getMethod("createMember", String.class, HttpHeaders.class, UriInfo.class);
+ args = new Object[] {"body", getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.POST, memberService, m, args, "body"));
+
+ //createMember
+ memberService = new TestMemberService("engineering");
+ m = memberService.getClass().getMethod("createMember", String.class, HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {"body", getHttpHeaders(), getUriInfo(), "joe"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.POST, memberService, m, args, "body"));
+
+ //deleteMember
+ memberService = new TestMemberService("engineering");
+ m = memberService.getClass().getMethod("deleteMember", HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo(), "joe"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.DELETE, memberService, m, args, null));
+
+ //getMembers
+ memberService = new TestMemberService("engineering");
+ m = memberService.getClass().getMethod("getMembers", HttpHeaders.class, UriInfo.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo()};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, memberService, m, args, null));
+
+ //getMember
+ memberService = new TestMemberService("engineering");
+ m = memberService.getClass().getMethod("getMember", HttpHeaders.class, UriInfo.class, String.class);
+ args = new Object[] {getHttpHeaders(), getUriInfo(), "joe"};
+ listInvocations.add(new ServiceTestInvocation(Request.Type.GET, memberService, m, args, null));
+
+ return listInvocations;
+ }
+
+ private class TestMemberService extends MemberService {
+ public TestMemberService(String groupName) {
+ super(groupName);
+ }
+
+ @Override
+ ResourceInstance createResource(Type type, Map<Type, String> mapIds) {
+ return getTestResource();
+ }
+
+ @Override
+ RequestFactory getRequestFactory() {
+ return getTestRequestFactory();
+ }
+
+ @Override
+ protected RequestBodyParser getBodyParser() {
+ return getTestBodyParser();
+ }
+
+ @Override
+ protected ResultSerializer getResultSerializer() {
+ return getTestResultSerializer();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
index 83a1a49..b3f40a5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
@@ -30,7 +30,9 @@ import java.util.Set;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.ClusterRequest;
import org.apache.ambari.server.controller.ConfigurationRequest;
+import org.apache.ambari.server.controller.GroupRequest;
import org.apache.ambari.server.controller.HostRequest;
+import org.apache.ambari.server.controller.MemberRequest;
import org.apache.ambari.server.controller.RequestStatusResponse;
import org.apache.ambari.server.controller.ServiceComponentHostRequest;
import org.apache.ambari.server.controller.StackConfigurationRequest;
@@ -47,7 +49,6 @@ import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
import org.apache.ambari.server.controller.spi.SystemException;
import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
import org.apache.ambari.server.controller.utilities.PredicateBuilder;
-import org.apache.ambari.server.state.State;
import org.easymock.EasyMock;
import org.easymock.IArgumentMatcher;
import org.junit.Assert;
@@ -297,7 +298,19 @@ public class AbstractResourceProviderTest {
EasyMock.reportMatcher(new UserRequestSetMatcher(name));
return null;
}
-
+
+ public static Set<GroupRequest> getGroupRequestSet(String name)
+ {
+ EasyMock.reportMatcher(new GroupRequestSetMatcher(name));
+ return null;
+ }
+
+ public static Set<MemberRequest> getMemberRequestSet(String groupname, String username)
+ {
+ EasyMock.reportMatcher(new MemberRequestSetMatcher(groupname, username));
+ return null;
+ }
+
public static Set<StackConfigurationRequest> getStackConfigurationRequestSet(String stackName, String stackVersion,
String serviceName, String propertyName)
{
@@ -547,7 +560,81 @@ public class AbstractResourceProviderTest {
stringBuffer.append("UserRequestSetMatcher(").append(userRequest).append(")");
}
}
-
+
+ /**
+ * Matcher for a GroupRequest set containing a single request.
+ */
+ public static class GroupRequestSetMatcher extends HashSet<GroupRequest> implements IArgumentMatcher {
+
+ private final GroupRequest groupRequest;
+
+ public GroupRequestSetMatcher(String name) {
+ this.groupRequest = new GroupRequest(name);
+ add(this.groupRequest);
+ }
+
+ @Override
+ public boolean matches(Object o) {
+
+ if (!(o instanceof Set)) {
+ return false;
+ }
+
+ Set set = (Set) o;
+
+ if (set.size() != 1) {
+ return false;
+ }
+
+ Object request = set.iterator().next();
+
+ return request instanceof GroupRequest &&
+ eq(((GroupRequest) request).getGroupName(), groupRequest.getGroupName());
+ }
+
+ @Override
+ public void appendTo(StringBuffer stringBuffer) {
+ stringBuffer.append("GroupRequestSetMatcher(").append(groupRequest).append(")");
+ }
+ }
+
+ /**
+ * Matcher for a MemberRequest set containing a single request.
+ */
+ public static class MemberRequestSetMatcher extends HashSet<MemberRequest> implements IArgumentMatcher {
+
+ private final MemberRequest memberRequest;
+
+ public MemberRequestSetMatcher(String groupname, String username) {
+ this.memberRequest = new MemberRequest(groupname, username);
+ add(this.memberRequest);
+ }
+
+ @Override
+ public boolean matches(Object o) {
+
+ if (!(o instanceof Set)) {
+ return false;
+ }
+
+ Set set = (Set) o;
+
+ if (set.size() != 1) {
+ return false;
+ }
+
+ Object request = set.iterator().next();
+
+ return request instanceof MemberRequest &&
+ eq(((MemberRequest) request).getGroupName(), memberRequest.getGroupName()) &&
+ eq(((MemberRequest) request).getUserName(), memberRequest.getUserName());
+ }
+
+ @Override
+ public void appendTo(StringBuffer stringBuffer) {
+ stringBuffer.append("MemberRequestSetMatcher(").append(memberRequest).append(")");
+ }
+ }
/**
* Matcher for a Stack set containing a single request.
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupResourceProviderTest.java
new file mode 100644
index 0000000..0cd1be1
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/GroupResourceProviderTest.java
@@ -0,0 +1,158 @@
+/**
+ * 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 static org.easymock.EasyMock.createMock;
+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 java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.GroupResponse;
+import org.apache.ambari.server.controller.RequestStatusResponse;
+import org.apache.ambari.server.controller.spi.Predicate;
+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.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * GroupResourceProvider tests.
+ */
+public class GroupResourceProviderTest {
+ @Test
+ public void testCreateResources() throws Exception {
+ Resource.Type type = Resource.Type.Group;
+
+ AmbariManagementController managementController = createMock(AmbariManagementController.class);
+ RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+
+ managementController.createGroups(AbstractResourceProviderTest.Matcher.getGroupRequestSet("engineering"));
+
+ // replay
+ replay(managementController, response);
+
+ ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+ type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ // add the property map to a set for the request. add more maps for multiple creates
+ Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
+
+ Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+ // add properties to the request map
+ properties.put(GroupResourceProvider.GROUP_GROUPNAME_PROPERTY_ID, "engineering");
+
+ propertySet.add(properties);
+
+ // create the request
+ Request request = PropertyHelper.getCreateRequest(propertySet, null);
+
+ provider.createResources(request);
+
+ // verify
+ verify(managementController, response);
+ }
+
+ @Test
+ public void testGetResources() throws Exception {
+ Resource.Type type = Resource.Type.Group;
+
+ AmbariManagementController managementController = createMock(AmbariManagementController.class);
+
+ Set<GroupResponse> allResponse = new HashSet<GroupResponse>();
+ allResponse.add(new GroupResponse("engineering", false));
+
+ // set expectations
+ expect(managementController.getGroups(AbstractResourceProviderTest.Matcher.getGroupRequestSet("engineering"))).
+ 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(GroupResourceProvider.GROUP_GROUPNAME_PROPERTY_ID);
+
+ Predicate predicate = new PredicateBuilder().property(GroupResourceProvider.GROUP_GROUPNAME_PROPERTY_ID).
+ equals("engineering").toPredicate();
+ Request request = PropertyHelper.getReadRequest(propertyIds);
+ Set<Resource> resources = provider.getResources(request, predicate);
+
+ Assert.assertEquals(1, resources.size());
+ for (Resource resource : resources) {
+ String groupName = (String) resource.getPropertyValue(GroupResourceProvider.GROUP_GROUPNAME_PROPERTY_ID);
+ Assert.assertEquals("engineering", groupName);
+ }
+
+ // verify
+ verify(managementController);
+ }
+
+ @Test
+ public void testUpdateResources() throws Exception {
+ // currently provider.updateResources() does nothing, nothing to test
+ }
+
+ @Test
+ public void testDeleteResources() throws Exception {
+ Resource.Type type = Resource.Type.Group;
+
+ AmbariManagementController managementController = createMock(AmbariManagementController.class);
+ RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+
+ // set expectations
+ managementController.deleteGroups(AbstractResourceProviderTest.Matcher.getGroupRequestSet("engineering"));
+
+ // replay
+ replay(managementController, response);
+
+ ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+ type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ Predicate predicate = new PredicateBuilder().property(GroupResourceProvider.GROUP_GROUPNAME_PROPERTY_ID).
+ equals("engineering").toPredicate();
+ provider.deleteResources(predicate);
+
+ // verify
+ verify(managementController, response);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/MemberResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/MemberResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/MemberResourceProviderTest.java
new file mode 100644
index 0000000..4860ddd
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/MemberResourceProviderTest.java
@@ -0,0 +1,128 @@
+/**
+ * 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 static org.easymock.EasyMock.anyObject;
+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.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RequestStatusResponse;
+import org.apache.ambari.server.controller.ResourceProviderFactory;
+import org.apache.ambari.server.controller.spi.Predicate;
+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.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.junit.Test;
+
+/**
+ * MemberResourceProvider tests.
+ */
+public class MemberResourceProviderTest {
+ @Test
+ public void testCreateResources() throws Exception {
+ Resource.Type type = Resource.Type.Member;
+
+ AmbariManagementController managementController = createMock(AmbariManagementController.class);
+ RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+ ResourceProviderFactory resourceProviderFactory = createNiceMock(ResourceProviderFactory.class);
+ ResourceProvider memberResourceProvider = createNiceMock(MemberResourceProvider.class);
+
+ AbstractControllerResourceProvider.init(resourceProviderFactory);
+
+ expect(resourceProviderFactory.getMemberResourceProvider(anyObject(Set.class), anyObject(Map.class),
+ eq(managementController))).andReturn(memberResourceProvider).anyTimes();
+ // replay
+ replay(managementController, response, resourceProviderFactory, memberResourceProvider);
+
+ ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+ type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ // add the property map to a set for the request. add more maps for multiple creates
+ Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
+
+ Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+ // add properties to the request map
+ properties.put(MemberResourceProvider.MEMBER_GROUP_NAME_PROPERTY_ID, "engineering");
+ properties.put(MemberResourceProvider.MEMBER_USER_NAME_PROPERTY_ID, "joe");
+
+ propertySet.add(properties);
+
+ // create the request
+ Request request = PropertyHelper.getCreateRequest(propertySet, null);
+
+ provider.createResources(request);
+
+ // verify
+ verify(managementController, response);
+ }
+
+ @Test
+ public void testUpdateResources() throws Exception {
+ // currently provider.updateResources() does nothing, nothing to test
+ }
+
+ @Test
+ public void testDeleteResources() throws Exception {
+ Resource.Type type = Resource.Type.Member;
+
+ AmbariManagementController managementController = createMock(AmbariManagementController.class);
+ RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
+ ResourceProviderFactory resourceProviderFactory = createNiceMock(ResourceProviderFactory.class);
+ ResourceProvider memberResourceProvider = createNiceMock(MemberResourceProvider.class);
+
+ AbstractControllerResourceProvider.init(resourceProviderFactory);
+
+ // set expectations
+ expect(resourceProviderFactory.getMemberResourceProvider(anyObject(Set.class), anyObject(Map.class),
+ eq(managementController))).andReturn(memberResourceProvider).anyTimes();
+
+ // replay
+ replay(managementController, response, resourceProviderFactory, memberResourceProvider);
+
+ ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+ type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ PredicateBuilder builder = new PredicateBuilder();
+ builder.property(MemberResourceProvider.MEMBER_GROUP_NAME_PROPERTY_ID).equals("engineering");
+ Predicate predicate = builder.toPredicate();
+ provider.deleteResources(predicate);
+
+ // verify
+ verify(managementController, response);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/GroupDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/GroupDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/GroupDAOTest.java
new file mode 100644
index 0000000..27dab37
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/GroupDAOTest.java
@@ -0,0 +1,83 @@
+/**
+ * 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.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertSame;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.entities.GroupEntity;
+
+/**
+ * GroupDAO unit tests.
+ */
+public class GroupDAOTest {
+
+ @Inject
+ DaoUtils daoUtils;
+
+ Provider<EntityManager> entityManagerProvider = createStrictMock(Provider.class);
+ EntityManager entityManager = createStrictMock(EntityManager.class);
+
+ @Before
+ public void init() {
+ reset(entityManagerProvider);
+ expect(entityManagerProvider.get()).andReturn(entityManager).atLeastOnce();
+ replay(entityManagerProvider);
+ }
+
+
+ @Test
+ public void testfindGroupByName() {
+ final String groupName = "engineering";
+ final GroupEntity entity = new GroupEntity();
+ entity.setGroupName(groupName);
+ TypedQuery<GroupEntity> query = createStrictMock(TypedQuery.class);
+
+ // set expectations
+ expect(entityManager.createNamedQuery(eq("groupByName"), eq(GroupEntity.class))).andReturn(query);
+ expect(query.setParameter("groupname", groupName)).andReturn(query);
+ expect(query.getSingleResult()).andReturn(entity);
+
+ replay(entityManager, query);
+
+ final GroupDAO dao = new GroupDAO();
+ dao.entityManagerProvider = entityManagerProvider;
+
+ final GroupEntity result = dao.findGroupByName(groupName);
+
+ assertSame(entity, result);
+
+ verify(entityManagerProvider, entityManager, query);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
index d5fc62a..aef0ea7 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
@@ -17,15 +17,22 @@
*/
package org.apache.ambari.server.security.authorization;
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.persist.PersistService;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import java.util.Properties;
+
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.MemberDAO;
import org.apache.ambari.server.orm.dao.RoleDAO;
import org.apache.ambari.server.orm.dao.UserDAO;
import org.apache.ambari.server.orm.entities.RoleEntity;
@@ -38,10 +45,10 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
-import java.util.List;
-import java.util.Properties;
-
-import static org.junit.Assert.*;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
public class TestUsers {
private Injector injector;
@@ -51,6 +58,10 @@ public class TestUsers {
@Inject
protected UserDAO userDAO;
@Inject
+ protected GroupDAO groupDAO;
+ @Inject
+ protected MemberDAO memberDAO;
+ @Inject
protected RoleDAO roleDAO;
@Inject
protected PasswordEncoder passwordEncoder;
@@ -96,6 +107,87 @@ public class TestUsers {
assertNotSame(userEntity.getUserPassword(), userDAO.findLocalUserByName("user").getUserPassword());
}
+ @Test
+ public void testCreateGroup() throws Exception {
+ final String groupName = "engineering";
+ users.createGroup(groupName);
+ assertNotNull(groupDAO.findGroupByName(groupName));
+ }
+
+ @Test
+ public void testGetGroup() throws Exception {
+ final String groupName = "engineering";
+ users.createGroup(groupName);
+
+ final Group group = users.getGroup(groupName);
+ assertNotNull(group);
+ assertEquals(false, group.isLdapGroup());
+ assertEquals(groupName, group.getGroupName());
+
+ assertNotNull(groupDAO.findGroupByName(groupName));
+ }
+
+ @Test
+ public void testGetAllGroups() throws Exception {
+ users.createGroup("one");
+ users.createGroup("two");
+
+ final List<Group> groupList = users.getAllGroups();
+
+ assertEquals(2, groupList.size());
+ assertEquals(2, groupDAO.findAll().size());
+ }
+
+ @Test
+ public void testRemoveGroup() throws Exception {
+ final String groupName = "engineering";
+ users.createGroup(groupName);
+ final Group group = users.getGroup(groupName);
+ assertEquals(1, users.getAllGroups().size());
+ users.removeGroup(group);
+ assertEquals(0, users.getAllGroups().size());
+ }
+
+ @Test
+ public void testAddMemberToGroup() throws Exception {
+ final String groupName = "engineering";
+ users.createGroup(groupName);
+ users.createUser("user", "user");
+ users.addMemberToGroup(groupName, "user");
+ assertEquals(1, groupDAO.findGroupByName(groupName).getMemberEntities().size());
+ }
+
+ @Test
+ public void testRemoveMemberFromGroup() throws Exception {
+ final String groupName = "engineering";
+ users.createGroup(groupName);
+ users.createUser("user", "user");
+ users.addMemberToGroup(groupName, "user");
+ assertEquals(1, groupDAO.findGroupByName(groupName).getMemberEntities().size());
+ users.removeMemberFromGroup(groupName, "user");
+ assertEquals(0, groupDAO.findGroupByName(groupName).getMemberEntities().size());
+ }
+
+ @Test
+ public void testGetGroupMembers() throws Exception {
+ final String groupNameTwoMembers = "engineering";
+ final String groupNameZeroMembers = "management";
+ users.createGroup(groupNameTwoMembers);
+ users.createGroup(groupNameZeroMembers);
+ users.createUser("user", "user");
+ users.createUser("admin", "admin");
+ users.addMemberToGroup(groupNameTwoMembers, "user");
+ users.addMemberToGroup(groupNameTwoMembers, "admin");
+
+ assertEquals(users.getGroupMembers(groupNameTwoMembers).size(), 2);
+ assertEquals(users.getGroupMembers(groupNameZeroMembers).size(), 0);
+ }
+
+ @Test
+ public void testGetGroupMembersUnexistingGroup() throws Exception {
+ assertEquals(users.getGroupMembers("unexisting"), null);
+ }
+
@Test(expected = AmbariException.class)
public void testModifyPassword() throws Exception {
users.createUser("user", "user");
@@ -132,12 +224,12 @@ public class TestUsers {
user = users.getLocalUser("admin");
assertFalse(user.getRoles().contains(users.getAdminRole()));
-
+
user = users.getLocalUser("admin2");
users.demoteAdmin(user);
}
-
+
@Test(expected = AmbariException.class)
public void testRemoveUser() throws Exception {
users.createUser("admin", "admin");
[2/2] git commit: AMBARI-6343. Views : Admin - Add Group and Group
Member Resources.
Posted by sw...@apache.org.
AMBARI-6343. Views : Admin - Add Group and Group Member Resources.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/00a4991e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/00a4991e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/00a4991e
Branch: refs/heads/trunk
Commit: 00a4991eecb205f7936929e7010856661f0ba59e
Parents: 01e9e76
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Tue Jul 1 13:42:32 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Tue Jul 1 13:42:32 2014 -0700
----------------------------------------------------------------------
.../api/resources/GroupResourceDefinition.java | 49 ++++
.../api/resources/MemberResourceDefinition.java | 47 ++++
.../resources/ResourceInstanceFactoryImpl.java | 10 +-
.../server/api/services/GroupService.java | 144 ++++++++++++
.../server/api/services/MemberService.java | 148 ++++++++++++
.../controller/AmbariManagementController.java | 209 +++++++++++------
.../AmbariManagementControllerImpl.java | 230 ++++++++++++++-----
.../server/controller/ControllerModule.java | 5 +
.../ambari/server/controller/GroupRequest.java | 38 +++
.../ambari/server/controller/GroupResponse.java | 62 +++++
.../ambari/server/controller/MemberRequest.java | 45 ++++
.../server/controller/MemberResponse.java | 64 ++++++
.../controller/ResourceProviderFactory.java | 8 +-
.../AbstractControllerResourceProvider.java | 6 +-
.../internal/GroupResourceProvider.java | 188 +++++++++++++++
.../internal/MemberResourceProvider.java | 191 +++++++++++++++
.../ambari/server/controller/spi/Resource.java | 4 +
.../apache/ambari/server/orm/dao/GroupDAO.java | 84 +++++++
.../apache/ambari/server/orm/dao/MemberDAO.java | 70 ++++++
.../ambari/server/orm/entities/GroupEntity.java | 120 ++++++++++
.../server/orm/entities/MemberEntity.java | 100 ++++++++
.../ambari/server/orm/entities/UserEntity.java | 27 ++-
.../server/security/authorization/Group.java | 53 +++++
.../server/security/authorization/Member.java | 53 +++++
.../server/security/authorization/Users.java | 166 ++++++++++++-
.../main/resources/Ambari-DDL-MySQL-CREATE.sql | 8 +
.../main/resources/Ambari-DDL-Oracle-CREATE.sql | 8 +
.../resources/Ambari-DDL-Postgres-CREATE.sql | 10 +
.../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 12 +
.../src/main/resources/META-INF/persistence.xml | 2 +
.../src/main/resources/key_properties.json | 7 +
.../src/main/resources/properties.json | 10 +
.../server/api/services/GroupServiceTest.java | 100 ++++++++
.../server/api/services/MemberServiceTest.java | 104 +++++++++
.../internal/AbstractResourceProviderTest.java | 93 +++++++-
.../internal/GroupResourceProviderTest.java | 158 +++++++++++++
.../internal/MemberResourceProviderTest.java | 128 +++++++++++
.../ambari/server/orm/dao/GroupDAOTest.java | 83 +++++++
.../security/authorization/TestUsers.java | 114 ++++++++-
39 files changed, 2797 insertions(+), 161 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/GroupResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/GroupResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/GroupResourceDefinition.java
new file mode 100644
index 0000000..783e04b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/GroupResourceDefinition.java
@@ -0,0 +1,49 @@
+/**
+ * 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.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Group Resource Definition.
+ */
+public class GroupResourceDefinition extends BaseResourceDefinition {
+ public GroupResourceDefinition() {
+ super(Resource.Type.Group);
+ }
+
+ @Override
+ public String getPluralName() {
+ return "groups";
+ }
+
+ @Override
+ public String getSingularName() {
+ return "group";
+ }
+
+ @Override
+ public Set<SubResourceDefinition> getSubResourceDefinitions() {
+ final Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
+ subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.Member));
+ return subResourceDefinitions;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/MemberResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/MemberResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/MemberResourceDefinition.java
new file mode 100644
index 0000000..ad209f2
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/MemberResourceDefinition.java
@@ -0,0 +1,47 @@
+/**
+ * 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.resources;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Member Resource Definition.
+ */
+public class MemberResourceDefinition extends BaseResourceDefinition {
+ public MemberResourceDefinition() {
+ super(Resource.Type.Member);
+ }
+
+ @Override
+ public String getPluralName() {
+ return "members";
+ }
+
+ @Override
+ public String getSingularName() {
+ return "member";
+ }
+
+ @Override
+ public Set<SubResourceDefinition> getSubResourceDefinitions() {
+ return Collections.emptySet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index e1428d8..9bf589f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -117,6 +117,14 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
resourceDefinition = new UserResourceDefinition();
break;
+ case Group:
+ resourceDefinition = new GroupResourceDefinition();
+ break;
+
+ case Member:
+ resourceDefinition = new MemberResourceDefinition();
+ break;
+
case Request:
resourceDefinition = new RequestResourceDefinition();
break;
@@ -217,7 +225,7 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
case Blueprint:
resourceDefinition = new BlueprintResourceDefinition();
break;
-
+
case HostComponentProcess:
resourceDefinition = new HostComponentProcessResourceDefinition();
break;
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/api/services/GroupService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/GroupService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/GroupService.java
new file mode 100644
index 0000000..ee71719
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/GroupService.java
@@ -0,0 +1,144 @@
+/**
+ * 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 javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+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 org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.Collections;
+
+/**
+ * Service responsible for user groups requests.
+ */
+@Path("/groups/")
+public class GroupService extends BaseService {
+ /**
+ * Gets all groups.
+ * Handles: GET /groups requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ */
+ @GET
+ @Produces("text/plain")
+ public Response getGroups(@Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createGroupResource(null));
+ }
+
+ /**
+ * Gets a single group.
+ * Handles: GET /groups/{groupName} requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param groupName the group name
+ * @return information regarding the specified group
+ */
+ @GET
+ @Path("{groupName}")
+ @Produces("text/plain")
+ public Response getGroup(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("groupName") String groupName) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createGroupResource(groupName));
+ }
+
+ /**
+ * Creates a group.
+ * Handles: POST /groups requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @return information regarding the created group
+ */
+ @POST
+ @Produces("text/plain")
+ public Response createGroup(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, body, ui, Request.Type.POST, createGroupResource(null));
+ }
+
+ /**
+ * Creates a group.
+ * Handles: POST /groups/{groupName} requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param groupName the group name
+ * @return information regarding the created group
+ *
+ * @deprecated Use requests to /groups instead.
+ */
+ @POST
+ @Deprecated
+ @Path("{groupName}")
+ @Produces("text/plain")
+ public Response createGroup(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("groupName") String groupName) {
+ return handleRequest(headers, body, ui, Request.Type.POST, createGroupResource(groupName));
+ }
+
+ /**
+ * Deletes a group.
+ * Handles: DELETE /groups/{groupName} requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param groupName the group name
+ * @return information regarding the deleted group
+ */
+ @DELETE
+ @Path("{groupName}")
+ @Produces("text/plain")
+ public Response deleteGroup(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("groupName") String groupName) {
+ return handleRequest(headers, null, ui, Request.Type.DELETE, createGroupResource(groupName));
+ }
+
+ /**
+ * Get the members sub-resource.
+ *
+ * @param groupName the group name
+ * @return the members service
+ */
+ @Path("{groupName}/members")
+ public MemberService getMemberHandler(@PathParam("groupName") String groupName) {
+ return new MemberService(groupName);
+ }
+
+ /**
+ * Create a group resource instance.
+ *
+ * @param groupName group name
+ *
+ * @return a group resource instance
+ */
+ private ResourceInstance createGroupResource(String groupName) {
+ return createResource(Resource.Type.Group,
+ Collections.singletonMap(Resource.Type.Group, groupName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/api/services/MemberService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/MemberService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/MemberService.java
new file mode 100644
index 0000000..72e194f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/MemberService.java
@@ -0,0 +1,148 @@
+/**
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+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 org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Service responsible for user membership requests.
+ */
+public class MemberService extends BaseService {
+ /**
+ * Name of the group.
+ */
+ private String groupName;
+
+ /**
+ * Constructor.
+ *
+ * @param groupName name of the group
+ */
+ public MemberService(String groupName) {
+ this.groupName = groupName;
+ }
+
+ /**
+ * Creates new members.
+ * Handles: POST /groups/{groupname}/members requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @return information regarding the created member
+ */
+ @POST
+ @Produces("text/plain")
+ public Response createMember(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, body, ui, Request.Type.POST, createMemberResource(groupName, null));
+ }
+
+ /**
+ * Creates a new member.
+ * Handles: POST /groups/{groupname}/members/{username} requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param userName the user name
+ * @return information regarding the created member
+ */
+ @POST
+ @Path("{userName}")
+ @Produces("text/plain")
+ public Response createMember(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("userName") String userName) {
+ return handleRequest(headers, body, ui, Request.Type.POST, createMemberResource(groupName, userName));
+ }
+
+ /**
+ * Deletes a member.
+ * Handles: DELETE /groups/{groupname}/members/{username} requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param userName the user name
+ * @return information regarding the deleted group
+ */
+ @DELETE
+ @Path("{userName}")
+ @Produces("text/plain")
+ public Response deleteMember(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("userName") String userName) {
+ return handleRequest(headers, null, ui, Request.Type.DELETE, createMemberResource(groupName, userName));
+ }
+
+ /**
+ * Gets all members.
+ * Handles: GET /groups/{groupname}/members requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @return information regarding all members
+ */
+ @GET
+ @Produces("text/plain")
+ public Response getMembers(@Context HttpHeaders headers, @Context UriInfo ui) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createMemberResource(groupName, null));
+ }
+
+ /**
+ * Gets member.
+ * Handles: GET /groups/{groupname}/members/{username} requests.
+ *
+ * @param headers http headers
+ * @param ui uri info
+ * @param userName the user name
+ * @return information regarding the specific member
+ */
+ @GET
+ @Path("{userName}")
+ @Produces("text/plain")
+ public Response getMember(@Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("userName") String userName) {
+ return handleRequest(headers, null, ui, Request.Type.GET, createMemberResource(groupName, userName));
+ }
+
+ /**
+ * Create a member resource instance.
+ *
+ * @param groupName group name
+ * @param userName user name
+ *
+ * @return a member resource instance
+ */
+ private ResourceInstance createMemberResource(String groupName, String userName) {
+ final Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+ mapIds.put(Resource.Type.Group, groupName);
+ mapIds.put(Resource.Type.Member, userName);
+ return createResource(Resource.Type.Member, mapIds);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index a18468a..dce77c5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -75,16 +75,34 @@ public interface AmbariManagementController {
*/
public void createConfiguration(ConfigurationRequest request)
throws AmbariException;
-
+
/**
* Creates users.
- *
- * @param requests the request objects which defines the user.
- *
+ *
+ * @param requests the request objects which define the user.
+ *
* @throws AmbariException when the user cannot be created.
*/
public void createUsers(Set<UserRequest> requests) throws AmbariException;
+ /**
+ * Creates groups.
+ *
+ * @param requests the request objects which define the groups.
+ *
+ * @throws AmbariException when the groups cannot be created.
+ */
+ public void createGroups(Set<GroupRequest> requests) throws AmbariException;
+
+ /**
+ * Creates members of the group.
+ *
+ * @param requests the request objects which define the members.
+ *
+ * @throws AmbariException when the members cannot be created.
+ */
+ public void createMembers(Set<MemberRequest> requests) throws AmbariException;
+
// ----- Read -------------------------------------------------------------
@@ -140,15 +158,39 @@ public interface AmbariManagementController {
/**
* Gets the users identified by the given request objects.
*
- * @param requests the request objects
- *
- * @return a set of user responses
- *
+ * @param requests the request objects
+ *
+ * @return a set of user responses
+ *
* @throws AmbariException if the users could not be read
*/
public Set<UserResponse> getUsers(Set<UserRequest> requests)
throws AmbariException;
-
+
+ /**
+ * Gets the user groups identified by the given request objects.
+ *
+ * @param requests the request objects
+ *
+ * @return a set of group responses
+ *
+ * @throws AmbariException if the groups could not be read
+ */
+ public Set<GroupResponse> getGroups(Set<GroupRequest> requests)
+ throws AmbariException;
+
+ /**
+ * Gets the group members identified by the given request objects.
+ *
+ * @param requests the request objects
+ *
+ * @return a set of member responses
+ *
+ * @throws AmbariException if the members could not be read
+ */
+ public Set<MemberResponse> getMembers(Set<MemberRequest> requests)
+ throws AmbariException;
+
// ----- Update -----------------------------------------------------------
@@ -186,16 +228,25 @@ public interface AmbariManagementController {
*/
public RequestStatusResponse updateHostComponents(
Set<ServiceComponentHostRequest> requests, Map<String, String> requestProperties, boolean runSmokeTest) throws AmbariException;
-
+
/**
* Updates the users specified.
- *
- * @param requests the users to modify
- *
- * @throws AmbariException if the resources cannot be updated
+ *
+ * @param requests the users to modify
+ *
+ * @throws AmbariException if the resources cannot be updated
*/
public void updateUsers(Set<UserRequest> requests) throws AmbariException;
+ /**
+ * Updates the groups specified.
+ *
+ * @param requests the groups to modify
+ *
+ * @throws AmbariException if the resources cannot be updated
+ */
+ public void updateGroups(Set<GroupRequest> requests) throws AmbariException;
+
// ----- Delete -----------------------------------------------------------
@@ -219,16 +270,34 @@ public interface AmbariManagementController {
*/
public RequestStatusResponse deleteHostComponents(
Set<ServiceComponentHostRequest> requests) throws AmbariException;
-
+
/**
* Deletes the users specified.
- *
- * @param requests the users to delete
- *
- * @throws AmbariException if the resources cannot be deleted
+ *
+ * @param requests the users to delete
+ *
+ * @throws AmbariException if the resources cannot be deleted
*/
public void deleteUsers(Set<UserRequest> requests) throws AmbariException;
-
+
+ /**
+ * Deletes the user groups specified.
+ *
+ * @param requests the groups to delete
+ *
+ * @throws AmbariException if the resources cannot be deleted
+ */
+ public void deleteGroups(Set<GroupRequest> requests) throws AmbariException;
+
+ /**
+ * Deletes the group members specified.
+ *
+ * @param requests the members to delete
+ *
+ * @throws AmbariException if the resources cannot be deleted
+ */
+ public void deleteMembers(Set<MemberRequest> requests) throws AmbariException;
+
/**
* Create the action defined by the attributes in the given request object.
*
@@ -239,14 +308,14 @@ public interface AmbariManagementController {
*/
public RequestStatusResponse createAction(ExecuteActionRequest actionRequest, Map<String, String> requestProperties)
throws AmbariException;
-
+
/**
* Get supported stacks.
- *
+ *
* @param requests the stacks
- *
+ *
* @return a set of stacks responses
- *
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<StackResponse> getStacks(Set<StackRequest> requests) throws AmbariException;
@@ -258,105 +327,105 @@ public interface AmbariManagementController {
* @throws AmbariException if
*/
public RequestStatusResponse updateStacks() throws AmbariException;
-
+
/**
* Get supported stacks versions.
- *
+ *
* @param requests the stacks versions
- *
+ *
* @return a set of stacks versions responses
- *
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<StackVersionResponse> getStackVersions(Set<StackVersionRequest> requests) throws AmbariException;
-
+
/**
* Get repositories by stack name, version and operating system.
- *
- * @param requests the repositories
- *
+ *
+ * @param requests the repositories
+ *
* @return a set of repositories
- *
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<RepositoryResponse> getRepositories(Set<RepositoryRequest> requests) throws AmbariException;
/**
* Updates repositories by stack name, version and operating system.
- *
+ *
* @param requests the repositories
- *
+ *
* @throws AmbariException
*/
void updateRespositories(Set<RepositoryRequest> requests) throws AmbariException;
-
+
/**
* Get repositories by stack name, version.
- *
- * @param requests the services
- *
+ *
+ * @param requests the services
+ *
* @return a set of services
- *
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<StackServiceResponse> getStackServices(Set<StackServiceRequest> requests) throws AmbariException;
-
+
/**
* Get configurations by stack name, version and service.
- *
- * @param requests the configurations
- *
+ *
+ * @param requests the configurations
+ *
* @return a set of configurations
- *
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<StackConfigurationResponse> getStackConfigurations(Set<StackConfigurationRequest> requests) throws AmbariException;
-
-
+
+
/**
* Get components by stack name, version and service.
- *
- * @param requests the components
- *
+ *
+ * @param requests the components
+ *
* @return a set of components
- *
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<StackServiceComponentResponse> getStackComponents(Set<StackServiceComponentRequest> requests) throws AmbariException;
-
-
+
+
/**
* Get operating systems by stack name, version.
- *
- * @param requests the operating systems
- *
- * @return a set of operating systems
- *
+ *
+ * @param requests the operating systems
+ *
+ * @return a set of operating systems
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<OperatingSystemResponse> getStackOperatingSystems(Set<OperatingSystemRequest> requests) throws AmbariException;
/**
* Get all top-level services of Ambari, not related to certain cluster.
- *
- * @param requests the top-level services
- *
- * @return a set of top-level services
- *
+ *
+ * @param requests the top-level services
+ *
+ * @return a set of top-level services
+ *
* @throws AmbariException if the resources cannot be read
*/
-
+
public Set<RootServiceResponse> getRootServices(Set<RootServiceRequest> requests) throws AmbariException;
/**
* Get all components of top-level services of Ambari, not related to certain cluster.
- *
- * @param requests the components of top-level services
- *
- * @return a set of components
- *
+ *
+ * @param requests the components of top-level services
+ *
+ * @return a set of components
+ *
* @throws AmbariException if the resources cannot be read
*/
public Set<RootServiceComponentResponse> getRootServiceComponents(Set<RootServiceComponentRequest> requests) throws AmbariException;
@@ -561,4 +630,4 @@ public interface AmbariManagementController {
public MaintenanceState getEffectiveMaintenanceState(ServiceComponentHost sch)
throws AmbariException;
}
-
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 1b81ce9..e392a71 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -85,6 +85,7 @@ import org.apache.ambari.server.metadata.ActionMetadata;
import org.apache.ambari.server.metadata.RoleCommandOrder;
import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.Group;
import org.apache.ambari.server.security.authorization.User;
import org.apache.ambari.server.security.authorization.Users;
import org.apache.ambari.server.stageplanner.RoleGraph;
@@ -197,7 +198,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
final private static String JDK_RESOURCE_LOCATION =
"/resources/";
-
+
final private static int REPO_URL_CONNECT_TIMEOUT = 3000;
final private static int REPO_URL_READ_TIMEOUT = 2000;
@@ -234,19 +235,19 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
} else {
this.masterProtocol = "http";
this.masterPort = configs.getClientApiPort();
- }
+ }
this.jdkResourceUrl = getAmbariServerURI(JDK_RESOURCE_LOCATION);
this.javaHome = configs.getJavaHome();
this.jdkName = configs.getJDKName();
this.jceName = configs.getJCEName();
this.ojdbcUrl = getAmbariServerURI(JDK_RESOURCE_LOCATION + "/" + configs.getOjdbcJarName());
this.mysqljdbcUrl = getAmbariServerURI(JDK_RESOURCE_LOCATION + "/" + configs.getMySQLJarName());
-
+
this.serverDB = configs.getServerDBName();
} else {
this.masterProtocol = null;
this.masterPort = null;
-
+
this.jdkResourceUrl = null;
this.javaHome = null;
this.jdkName = null;
@@ -256,17 +257,17 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
this.serverDB = null;
}
}
-
+
public String getAmbariServerURI(String path) {
if(masterProtocol==null || masterHostname==null || masterPort==null)
return null;
-
+
URIBuilder uriBuilder = new URIBuilder();
uriBuilder.setScheme(masterProtocol);
uriBuilder.setHost(masterHostname);
uriBuilder.setPort(masterPort);
uriBuilder.setPath(path);
-
+
return uriBuilder.toString();
}
@@ -563,8 +564,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
}
}
- }
-
+ }
+
private void setRestartRequiredServices(
Service service, String hostName) throws AmbariException {
@@ -661,6 +662,54 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
}
+ @Override
+ public void createGroups(Set<GroupRequest> requests) throws AmbariException {
+ for (GroupRequest request : requests) {
+ if (StringUtils.isBlank(request.getGroupName())) {
+ throw new AmbariException("Group name must be supplied.");
+ }
+ final Group group = users.getGroup(request.getGroupName());
+ if (group != null) {
+ throw new AmbariException("Group already exists.");
+ }
+ users.createGroup(request.getGroupName());
+ }
+ }
+
+ @Override
+ public void createMembers(Set<MemberRequest> requests) throws AmbariException {
+ for (MemberRequest request : requests) {
+ if (StringUtils.isBlank(request.getGroupName()) || StringUtils.isBlank(request.getUserName())) {
+ throw new AmbariException("Both group name and user name must be supplied.");
+ }
+ users.addMemberToGroup(request.getGroupName(), request.getUserName());
+ }
+ }
+
+ @Override
+ public Set<MemberResponse> getMembers(Set<MemberRequest> requests)
+ throws AmbariException {
+ final Set<MemberResponse> responses = new HashSet<MemberResponse>();
+ for (MemberRequest request: requests) {
+ LOG.debug("Received a getMembers request, " + request.toString());
+ final Group group = users.getGroup(request.getGroupName());
+ if (null == group) {
+ if (requests.size() == 1) {
+ // only throw exception if there is a single request
+ // if there are multiple requests, this indicates an OR predicate
+ throw new ObjectNotFoundException("Cannot find group '"
+ + request.getGroupName() + "'");
+ }
+ } else {
+ for (User user: users.getGroupMembers(group.getGroupName())) {
+ final MemberResponse response = new MemberResponse(group.getGroupName(), user.getUserName());
+ responses.add(response);
+ }
+ }
+ }
+ return responses;
+ }
+
private Stage createNewStage(long id, Cluster cluster, long requestId, String requestContext, String clusterHostInfo) {
String logDir = BASE_LOG_DIR + File.pathSeparator + requestId;
Stage stage =
@@ -672,7 +721,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
return stage;
}
-
private Set<ClusterResponse> getClusters(ClusterRequest request)
throws AmbariException {
@@ -684,7 +732,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
+ ", clusterId=" + request.getClusterId()
+ ", stackInfo=" + request.getStackVersion());
}
-
+
if (request.getClusterName() != null) {
Cluster c = clusters.getCluster(request.getClusterName());
ClusterResponse cr = c.convertToResponse();
@@ -900,7 +948,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
if (host == null) {
throw new HostNotFoundException(cluster.getClusterName(), sch.getHostName());
}
-
+
r.setMaintenanceState(maintenanceStateHelper.getEffectiveState(sch, host).name());
response.add(r);
}
@@ -909,14 +957,14 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
return response;
}
-
+
@Override
public MaintenanceState getEffectiveMaintenanceState(ServiceComponentHost sch)
throws AmbariException {
-
+
return maintenanceStateHelper.getEffectiveState(sch);
}
-
+
private Set<ConfigurationResponse> getConfigurations(
ConfigurationRequest request) throws AmbariException {
@@ -1008,7 +1056,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
ConfigurationRequest cr = request.getDesiredConfig();
Config oldConfig = cluster.getDesiredConfigByType(cr.getType());
-
+
if (null != cr.getProperties()) {
// !!! empty property sets are supported, and need to be able to use
// previously-defined configs (revert)
@@ -1016,11 +1064,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
if (null == all || // none set
!all.containsKey(cr.getVersionTag()) || // tag not set
cr.getProperties().size() > 0) { // properties to set
-
+
LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to cluster ''{1}''",
cr.getVersionTag(),
request.getClusterName()));
-
+
cr.setClusterName(cluster.getClusterName());
createConfiguration(cr);
}
@@ -1029,7 +1077,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
Config baseConfig = cluster.getConfig(cr.getType(), cr.getVersionTag());
if (null != baseConfig) {
String authName = getAuthName();
-
+
if (cluster.addDesiredConfig(authName, baseConfig)) {
Logger logger = LoggerFactory.getLogger("configchange");
logger.info("cluster '" + request.getClusterName() + "' "
@@ -1056,7 +1104,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
clusters.mapHostsToCluster(
request.getHostNames(), request.getClusterName());
}
-
+
// set the provisioning state of the cluster
if (null != request.getProvisioningState()) {
State oldProvisioningState = cluster.getProvisioningState();
@@ -1077,12 +1125,12 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
if (provisioningState != oldProvisioningState) {
boolean isStateTransitionValid = State.isValidDesiredStateTransition(
oldProvisioningState, provisioningState);
-
+
if (!isStateTransitionValid) {
LOG.warn(
"Invalid cluster provisioning state {} cannot be set on the cluster {} because the current state is {}",
provisioningState, request.getClusterName(), oldProvisioningState);
-
+
throw new AmbariException("Invalid transition for"
+ " cluster provisioning state" + ", clusterName="
+ cluster.getClusterName() + ", clusterId="
@@ -1091,10 +1139,10 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
+ provisioningState);
}
}
-
+
cluster.setProvisioningState(provisioningState);
}
-
+
return null;
}
@@ -1694,7 +1742,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
requestParameters = new HashMap<String, String>();
requestParameters.put(keyName, requestProperties.get(keyName));
}
-
+
createHostAction(cluster, stage, scHost, configurations, configTags,
roleCommand, requestParameters, event);
}
@@ -1746,7 +1794,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
hostLevelParams.put(ORACLE_JDBC_URL, getOjdbcUrl());
hostLevelParams.put(DB_DRIVER_FILENAME, configs.getMySQLJarName());
hostLevelParams.putAll(getRcaParameters());
-
+
return hostLevelParams;
}
@@ -1857,7 +1905,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
Set<State> seenNewStates = new HashSet<State>();
Map<ServiceComponentHost, State> directTransitionScHosts = new HashMap<ServiceComponentHost, State>();
Set<String> maintenanceClusters = new HashSet<String>();
-
+
for (ServiceComponentHostRequest request : requests) {
validateServiceComponentHostRequest(request);
@@ -1921,13 +1969,13 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
+ " desired state, desiredState=" + newState.toString());
}
}
-
+
if (null != request.getMaintenanceState()) {
MaintenanceStateHelper psh = injector.getInstance(MaintenanceStateHelper.class);
-
+
MaintenanceState newMaint = MaintenanceState.valueOf(request.getMaintenanceState());
MaintenanceState oldMaint = psh.getEffectiveState(sch);
-
+
if (newMaint != oldMaint) {
if (sc.isClientComponent()) {
throw new IllegalArgumentException("Invalid arguments, cannot set " +
@@ -1938,7 +1986,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
"maintenance state to one of " + EnumSet.of(MaintenanceState.OFF, MaintenanceState.ON));
} else {
sch.setMaintenanceState(newMaint);
-
+
maintenanceClusters.add(sch.getClusterName());
}
}
@@ -2062,7 +2110,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
throw new AmbariException("Internal error - not supported transition", e);
}
}
-
+
if (maintenanceClusters.size() > 0) {
try {
maintenanceStateHelper.createRequests(this, requestProperties, maintenanceClusters);
@@ -2158,7 +2206,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
for (String role : roolesToDelete) {
users.removeRoleFromUser(u, role);
u.getRoles().remove(role);
- }
+ }
roolesToAdd.removeAll(u.getRoles());
for (String role : roolesToAdd) {
users.addRoleToUser(u, role);
@@ -2191,7 +2239,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
Set<ServiceComponentHostRequest> requests) throws AmbariException {
Set<ServiceComponentHostRequest> expanded = new HashSet<ServiceComponentHostRequest>();
-
+
// if any request are for the whole host, they need to be expanded
for (ServiceComponentHostRequest request : requests) {
if (null == request.getComponentName()) {
@@ -2200,7 +2248,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
throw new IllegalArgumentException("Cluster name and hostname must be specified.");
}
Cluster cluster = clusters.getCluster(request.getClusterName());
-
+
for (ServiceComponentHost sch : cluster.getServiceComponentHosts(request.getHostname())) {
ServiceComponentHostRequest schr = new ServiceComponentHostRequest(request.getClusterName(),
sch.getServiceName(), sch.getServiceComponentName(), sch.getHostName(), null);
@@ -2211,9 +2259,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
expanded.add(request);
}
}
-
+
Map<ServiceComponent, Set<ServiceComponentHost>> safeToRemoveSCHs = new HashMap<ServiceComponent, Set<ServiceComponentHost>>();
-
+
for (ServiceComponentHostRequest request : expanded) {
validateServiceComponentHostRequest(request);
@@ -2256,7 +2304,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
setRestartRequiredServices(service, request.getHostname());
-
+
if (!safeToRemoveSCHs.containsKey(component)) {
safeToRemoveSCHs.put(component, new HashSet<ServiceComponentHost>());
}
@@ -2276,7 +2324,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
return null;
}
-
+
@Override
public void deleteUsers(Set<UserRequest> requests)
throws AmbariException {
@@ -2292,6 +2340,25 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
}
+ @Override
+ public void deleteGroups(Set<GroupRequest> requests) throws AmbariException {
+ for (GroupRequest request: requests) {
+ LOG.debug("Received a delete group request, groupname=" + request.getGroupName());
+ final Group group = users.getGroup(request.getGroupName());
+ if (group != null) {
+ users.removeGroup(group);
+ }
+ }
+ }
+
+ @Override
+ public void deleteMembers(java.util.Set<MemberRequest> requests) throws AmbariException {
+ for (MemberRequest request : requests) {
+ LOG.debug("Received a delete member request, " + request);
+ users.removeMemberFromGroup(request.getGroupName(), request.getUserName());
+ }
+ }
+
/**
* Get a request response for the given request ids. Note that this method
* fully populates a request resource including the set of task sub-resources
@@ -2470,6 +2537,47 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
return responses;
}
+ @Override
+ public Set<GroupResponse> getGroups(Set<GroupRequest> requests)
+ throws AmbariException {
+ final Set<GroupResponse> responses = new HashSet<GroupResponse>();
+ for (GroupRequest request: requests) {
+ LOG.debug("Received a getGroups request, groupRequest=" + request.toString());
+ // get them all
+ if (null == request.getGroupName()) {
+ for (Group group: users.getAllGroups()) {
+ final GroupResponse response = new GroupResponse(group.getGroupName(), group.isLdapGroup());
+ responses.add(response);
+ }
+ } else {
+ final Group group = users.getGroup(request.getGroupName());
+ if (null == group) {
+ if (requests.size() == 1) {
+ // only throw exception if there is a single request
+ // if there are multiple requests, this indicates an OR predicate
+ throw new ObjectNotFoundException("Cannot find group '"
+ + request.getGroupName() + "'");
+ }
+ } else {
+ final GroupResponse response = new GroupResponse(group.getGroupName(), group.isLdapGroup());
+ responses.add(response);
+ }
+ }
+ }
+ return responses;
+ }
+
+ @Override
+ public void updateGroups(Set<GroupRequest> requests) throws AmbariException {
+ for (GroupRequest request: requests) {
+ final Group group = users.getGroup(request.getGroupName());
+ if (group == null) {
+ continue;
+ }
+ // currently no group updates are supported
+ }
+ }
+
private String getClientHostForRunningAction(Cluster cluster,
Service service) throws AmbariException {
StackId stackId = service.getDesiredStackVersion();
@@ -2527,7 +2635,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
Map<String, String> requestProperties)
throws AmbariException {
String clusterName = actionRequest.getClusterName();
-
+
String requestContext = "";
if (requestProperties != null) {
@@ -2546,25 +2654,25 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
+ ", clusterName=" + actionRequest.getClusterName()
+ ", request=" + actionRequest.toString());
}
-
+
ActionExecutionContext actionExecContext = getActionExecutionContext(actionRequest);
if (actionRequest.isCommand()) {
customCommandExecutionHelper.validateAction(actionRequest);
} else {
actionExecutionHelper.validateAction(actionRequest);
}
-
+
Map<String, String> params = new HashMap<String, String>();
Map<String, Set<String>> clusterHostInfo = new HashMap<String, Set<String>>();
String clusterHostInfoJson = "{}";
-
+
if (null != cluster) {
clusterHostInfo = StageUtils.getClusterHostInfo(
clusters.getHostsForCluster(cluster.getClusterName()), cluster);
params = createDefaultHostParams(cluster);
clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
}
-
+
Stage stage = createNewStage(0, cluster, actionManager.getNextRequestId(), requestContext, clusterHostInfoJson);
if (actionRequest.isCommand()) {
@@ -2573,7 +2681,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
} else {
actionExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage, params);
}
-
+
RoleGraph rg = null;
if (null != cluster) {
RoleCommandOrder rco = getRoleCommandOrder(cluster);
@@ -2581,10 +2689,10 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
} else {
rg = new RoleGraph();
}
-
- rg.build(stage);
+
+ rg.build(stage);
List<Stage> stages = rg.getStages();
-
+
if (stages != null && !stages.isEmpty()) {
actionManager.sendActions(stages, actionRequest);
return getRequestStatusResponse(stage.getRequestId());
@@ -2671,7 +2779,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
return response;
}
-
+
private Set<RepositoryResponse> getRepositories(RepositoryRequest request) throws AmbariException {
String stackName = request.getStackName();
@@ -2693,22 +2801,22 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
RepositoryInfo repository = this.ambariMetaInfo.getRepository(stackName, stackVersion, osType, repoId);
response = Collections.singleton(repository.convertToResponse());
}
-
+
return response;
}
-
+
@Override
public void updateRespositories(Set<RepositoryRequest> requests) throws AmbariException {
for (RepositoryRequest rr : requests) {
if (null == rr.getStackName() || rr.getStackName().isEmpty())
throw new AmbariException("Stack name must be specified.");
-
+
if (null == rr.getStackVersion() || rr.getStackVersion().isEmpty())
throw new AmbariException("Stack version must be specified.");
-
+
if (null == rr.getOsType() || rr.getOsType().isEmpty())
throw new AmbariException("OS type must be specified.");
-
+
if (null == rr.getRepoId() || rr.getRepoId().isEmpty())
throw new AmbariException("Repo ID must be specified.");
@@ -2725,19 +2833,19 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
String repoName = repositoryInfo.getRepoName();
boolean bFound = false;
-
+
String[] suffixes = configs.getRepoValidationSuffixes(rr.getOsType());
for (int i = 0; i < suffixes.length && !bFound; i++) {
String suffix = String.format(suffixes[i], repoName);
String spec = rr.getBaseUrl();
-
+
if (spec.charAt(spec.length()-1) != '/' && suffix.charAt(0) != '/')
spec = rr.getBaseUrl() + "/" + suffix;
else if (spec.charAt(spec.length()-1) == '/' && suffix.charAt(0) == '/')
spec = rr.getBaseUrl() + suffix.substring(1);
else
spec = rr.getBaseUrl() + suffix;
-
+
try {
IOUtils.readLines(usp.readFrom(spec));
bFound = true;
@@ -2745,7 +2853,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
LOG.error("IOException loading the base URL", ioe);
}
}
-
+
if (bFound) {
ambariMetaInfo.updateRepoBaseURL(rr.getStackName(),
rr.getStackVersion(), rr.getOsType(), rr.getRepoId(),
@@ -3008,7 +3116,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
return response;
}
-
+
@Override
public String getAuthName() {
return AuthorizationHelper.getAuthenticatedName(configs.getAnonymousAuditName());
@@ -3137,7 +3245,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
public String getMysqljdbcUrl() {
return mysqljdbcUrl;
}
-
+
public Map<String, String> getRcaParameters() {
String hostName = StageUtils.getHostName();
@@ -3157,5 +3265,5 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
return rcaParameters;
}
-
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index c132b1d..fc049a4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -26,6 +26,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Names;
import com.google.inject.persist.PersistModule;
import com.google.inject.persist.jpa.AmbariJpaPersistModule;
+
import org.apache.ambari.server.actionmanager.ActionDBAccessor;
import org.apache.ambari.server.actionmanager.ActionDBAccessorImpl;
import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
@@ -37,6 +38,7 @@ import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
import org.apache.ambari.server.controller.internal.HostComponentResourceProvider;
import org.apache.ambari.server.controller.internal.HostResourceProvider;
+import org.apache.ambari.server.controller.internal.MemberResourceProvider;
import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.orm.DBAccessor;
@@ -74,10 +76,12 @@ import org.apache.ambari.server.state.scheduler.RequestExecutionImpl;
import org.apache.ambari.server.state.svccomphost.ServiceComponentHostImpl;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
+
import java.security.SecureRandom;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
+
import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_JDBC_DDL_FILE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_ONLY;
import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_OR_EXTEND;
@@ -252,6 +256,7 @@ public class ControllerModule extends AbstractModule {
.implement(ResourceProvider.class, Names.named("hostComponent"), HostComponentResourceProvider.class)
.implement(ResourceProvider.class, Names.named("service"), ServiceResourceProvider.class)
.implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class)
+ .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class)
.build(ResourceProviderFactory.class));
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupRequest.java
new file mode 100644
index 0000000..1bc18cc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupRequest.java
@@ -0,0 +1,38 @@
+/**
+ * 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;
+
+/**
+ * Represents a group maintenance request.
+ */
+public class GroupRequest {
+ private final String groupName;
+
+ public GroupRequest(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ @Override
+ public String toString() {
+ return "GroupRequest [groupName=" + groupName + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupResponse.java
new file mode 100644
index 0000000..ef28f61
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/GroupResponse.java
@@ -0,0 +1,62 @@
+/**
+ * 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;
+
+/**
+ * Represents a user group maintenance response.
+ */
+public class GroupResponse {
+ private final String groupName;
+ private final boolean ldapGroup;
+
+ public GroupResponse(String groupName, boolean ldapGroup) {
+ this.groupName = groupName;
+ this.ldapGroup = ldapGroup;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public boolean isLdapGroup() {
+ return ldapGroup;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ GroupResponse that = (GroupResponse) o;
+
+ if (groupName != null ? !groupName.equals(that.groupName)
+ : that.groupName != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = groupName != null ? groupName.hashCode() : 0;
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberRequest.java
new file mode 100644
index 0000000..0245f36
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberRequest.java
@@ -0,0 +1,45 @@
+/**
+ * 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;
+
+/**
+ * Represents a member maintenance request.
+ */
+public class MemberRequest {
+ private final String groupName;
+ private final String userName;
+
+ public MemberRequest(String groupName, String userName) {
+ this.groupName = groupName;
+ this.userName = userName;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ @Override
+ public String toString() {
+ return "MemberRequest [groupName=" + groupName + ", userName=" + userName
+ + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberResponse.java
new file mode 100644
index 0000000..3dc6558
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/MemberResponse.java
@@ -0,0 +1,64 @@
+/**
+ * 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;
+
+public class MemberResponse {
+ private final String groupName;
+ private final String userName;
+
+ public MemberResponse(String groupName, String userName) {
+ this.groupName = groupName;
+ this.userName = userName;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ MemberResponse that = (MemberResponse) o;
+
+ if (groupName != null ? !groupName.equals(that.groupName)
+ : that.groupName != null) {
+ return false;
+ }
+ if (userName != null ? !userName.equals(that.userName)
+ : that.userName != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = groupName != null ? groupName.hashCode() : 0;
+ result = 31 * result + (userName != null ? userName.hashCode() : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 0113d75..a5f5b05 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -37,15 +37,19 @@ public interface ResourceProviderFactory {
ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds,
Map<Type, String> keyPropertyIds,
AmbariManagementController managementController);
-
+
@Named("service")
ResourceProvider getServiceResourceProvider(Set<String> propertyIds,
Map<Type, String> keyPropertyIds,
AmbariManagementController managementController);
-
+
@Named("component")
ResourceProvider getComponentResourceProvider(Set<String> propertyIds,
Map<Type, String> keyPropertyIds,
AmbariManagementController managementController);
+ @Named("member")
+ ResourceProvider getMemberResourceProvider(Set<String> propertyIds,
+ Map<Type, String> keyPropertyIds,
+ AmbariManagementController managementController);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index a62b0d4..f68f21c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -57,7 +57,7 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
super(propertyIds, keyPropertyIds);
this.managementController = managementController;
}
-
+
public static void init(ResourceProviderFactory factory) {
resourceProviderFactory = factory;
}
@@ -112,6 +112,10 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
return new TaskResourceProvider(propertyIds, keyPropertyIds, managementController);
case User:
return new UserResourceProvider(propertyIds, keyPropertyIds, managementController);
+ case Group:
+ return new GroupResourceProvider(propertyIds, keyPropertyIds, managementController);
+ case Member:
+ return resourceProviderFactory.getMemberResourceProvider(propertyIds, keyPropertyIds, managementController);
case Stack:
return new StackResourceProvider(propertyIds, keyPropertyIds, managementController);
case StackVersion:
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupResourceProvider.java
new file mode 100644
index 0000000..36e1007
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/GroupResourceProvider.java
@@ -0,0 +1,188 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.GroupRequest;
+import org.apache.ambari.server.controller.GroupResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+
+/**
+ * Resource provider for group resources.
+ */
+class GroupResourceProvider extends AbstractControllerResourceProvider {
+
+ // ----- Property ID constants ---------------------------------------------
+
+ // Groups
+ protected static final String GROUP_GROUPNAME_PROPERTY_ID = PropertyHelper.getPropertyId("Groups", "group_name");
+ protected static final String GROUP_LDAP_GROUP_PROPERTY_ID = PropertyHelper.getPropertyId("Groups", "ldap_group");
+
+ private static Set<String> pkPropertyIds =
+ new HashSet<String>(Arrays.asList(new String[]{
+ GROUP_GROUPNAME_PROPERTY_ID}));
+
+ /**
+ * Create a new resource provider for the given management controller.
+ *
+ * @param propertyIds the property ids
+ * @param keyPropertyIds the key property ids
+ * @param managementController the management controller
+ */
+ GroupResourceProvider(Set<String> propertyIds,
+ Map<Resource.Type, String> keyPropertyIds,
+ AmbariManagementController managementController) {
+ super(propertyIds, keyPropertyIds, managementController);
+ }
+
+ @Override
+ public RequestStatus createResources(Request request)
+ throws SystemException,
+ UnsupportedPropertyException,
+ ResourceAlreadyExistsException,
+ NoSuchParentResourceException {
+ final Set<GroupRequest> requests = new HashSet<GroupRequest>();
+ for (Map<String, Object> propertyMap : request.getProperties()) {
+ requests.add(getRequest(propertyMap));
+ }
+
+ createResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ getManagementController().createGroups(requests);
+ return null;
+ }
+ });
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public Set<Resource> getResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+ final Set<GroupRequest> requests = new HashSet<GroupRequest>();
+
+ if (predicate == null) {
+ requests.add(getRequest(null));
+ } else {
+ for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+ requests.add(getRequest(propertyMap));
+ }
+ }
+
+ Set<GroupResponse> responses = getResources(new Command<Set<GroupResponse>>() {
+ @Override
+ public Set<GroupResponse> invoke() throws AmbariException {
+ return getManagementController().getGroups(requests);
+ }
+ });
+
+ LOG.debug("Found group responses matching get group request"
+ + ", groupRequestSize=" + requests.size() + ", groupResponseSize="
+ + responses.size());
+
+ Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+ Set<Resource> resources = new HashSet<Resource>();
+
+ for (GroupResponse groupResponse : responses) {
+ ResourceImpl resource = new ResourceImpl(Resource.Type.Group);
+
+ setResourceProperty(resource, GROUP_GROUPNAME_PROPERTY_ID,
+ groupResponse.getGroupName(), requestedIds);
+
+ setResourceProperty(resource, GROUP_LDAP_GROUP_PROPERTY_ID,
+ groupResponse.isLdapGroup(), requestedIds);
+
+ resources.add(resource);
+ }
+
+ return resources;
+ }
+
+ @Override
+ public RequestStatus updateResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+ final Set<GroupRequest> requests = new HashSet<GroupRequest>();
+
+ for (Map<String, Object> propertyMap : getPropertyMaps(request.getProperties().iterator().next(), predicate)) {
+ final GroupRequest req = getRequest(propertyMap);
+ requests.add(req);
+ }
+
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ getManagementController().updateGroups(requests);
+ return null;
+ }
+ });
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public RequestStatus deleteResources(Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+ final Set<GroupRequest> requests = new HashSet<GroupRequest>();
+
+ for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+ final GroupRequest req = getRequest(propertyMap);
+ requests.add(req);
+ }
+
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ getManagementController().deleteGroups(requests);
+ return null;
+ }
+ });
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return pkPropertyIds;
+ }
+
+ private GroupRequest getRequest(Map<String, Object> properties) {
+ if (properties == null) {
+ return new GroupRequest(null);
+ }
+
+ final GroupRequest request = new GroupRequest((String) properties.get(GROUP_GROUPNAME_PROPERTY_ID));
+ return request;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MemberResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MemberResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MemberResourceProvider.java
new file mode 100644
index 0000000..27b7e4b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MemberResourceProvider.java
@@ -0,0 +1,191 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.MemberRequest;
+import org.apache.ambari.server.controller.MemberResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+import com.google.inject.persist.Transactional;
+
+/**
+ * Resource provider for member resources.
+ */
+public class MemberResourceProvider extends AbstractControllerResourceProvider {
+
+ // ----- Property ID constants ---------------------------------------------
+
+ // Members
+ protected static final String MEMBER_GROUP_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("MemberInfo", "group_name");
+ protected static final String MEMBER_USER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("MemberInfo", "user_name");
+
+ private static Set<String> pkPropertyIds =
+ new HashSet<String>(Arrays.asList(new String[]{
+ MEMBER_GROUP_NAME_PROPERTY_ID,
+ MEMBER_USER_NAME_PROPERTY_ID}));
+
+ /**
+ * Create a new resource provider for the given management controller.
+ *
+ * @param propertyIds the property ids
+ * @param keyPropertyIds the key property ids
+ * @param managementController the management controller
+ */
+ @AssistedInject
+ public MemberResourceProvider(@Assisted Set<String> propertyIds,
+ @Assisted Map<Resource.Type, String> keyPropertyIds,
+ @Assisted AmbariManagementController managementController) {
+ super(propertyIds, keyPropertyIds, managementController);
+ }
+
+ @Override
+ public RequestStatus createResources(Request request)
+ throws SystemException,
+ UnsupportedPropertyException,
+ ResourceAlreadyExistsException,
+ NoSuchParentResourceException {
+
+ final Set<MemberRequest> requests = new HashSet<MemberRequest>();
+ for (Map<String, Object> propertyMap : request.getProperties()) {
+ requests.add(getRequest(propertyMap));
+ }
+ createResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ getManagementController().createMembers(requests);
+ return null;
+ }
+ });
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ @Transactional
+ public Set<Resource> getResources(Request request, Predicate predicate) throws
+ SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+ final Set<MemberRequest> requests = new HashSet<MemberRequest>();
+ for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+ requests.add(getRequest(propertyMap));
+ }
+
+ Set<MemberResponse> responses = getResources(new Command<Set<MemberResponse>>() {
+ @Override
+ public Set<MemberResponse> invoke() throws AmbariException {
+ return getManagementController().getMembers(requests);
+ }
+ });
+
+ LOG.debug("Found member responses matching get members request"
+ + ", membersRequestSize=" + requests.size() + ", membersResponseSize="
+ + responses.size());
+
+ Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+ Set<Resource> resources = new HashSet<Resource>();
+
+ for (MemberResponse memberResponse : responses) {
+ ResourceImpl resource = new ResourceImpl(Resource.Type.Member);
+
+ setResourceProperty(resource, MEMBER_GROUP_NAME_PROPERTY_ID,
+ memberResponse.getGroupName(), requestedIds);
+
+ setResourceProperty(resource, MEMBER_USER_NAME_PROPERTY_ID,
+ memberResponse.getUserName(), requestedIds);
+
+ resources.add(resource);
+ }
+
+ return resources;
+ }
+
+ @Override
+ public RequestStatus updateResources(final Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+ final Set<MemberRequest> requests = new HashSet<MemberRequest>();
+ for (Map<String, Object> propertyMap : request.getProperties()) {
+ requests.add(getRequest(propertyMap));
+ }
+
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ // do nothing
+ return null;
+ }
+ });
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public RequestStatus deleteResources(Predicate predicate)
+ throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+ final Set<MemberRequest> requests = new HashSet<MemberRequest>();
+
+ for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+ final MemberRequest req = getRequest(propertyMap);
+ requests.add(req);
+ }
+
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ getManagementController().deleteMembers(requests);
+ return null;
+ }
+ });
+
+ return getRequestStatus(null);
+ }
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return pkPropertyIds;
+ }
+
+ private MemberRequest getRequest(Map<String, Object> properties) {
+ if (properties == null) {
+ return new MemberRequest(null, null);
+ }
+
+ final MemberRequest request = new MemberRequest(
+ (String) properties.get(MEMBER_GROUP_NAME_PROPERTY_ID),
+ (String) properties.get(MEMBER_USER_NAME_PROPERTY_ID));
+ return request;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 13e7c77..363ee0d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -86,6 +86,8 @@ public interface Resource {
RequestSchedule,
Task,
User,
+ Group,
+ Member,
Stack,
StackVersion,
OperatingSystem,
@@ -154,6 +156,8 @@ public interface Resource {
public static final Type RequestSchedule = InternalType.RequestSchedule.getType();
public static final Type Task = InternalType.Task.getType();
public static final Type User = InternalType.User.getType();
+ public static final Type Group = InternalType.Group.getType();
+ public static final Type Member = InternalType.Member.getType();
public static final Type Stack = InternalType.Stack.getType();
public static final Type StackVersion = InternalType.StackVersion.getType();
public static final Type OperatingSystem = InternalType.OperatingSystem.getType();
http://git-wip-us.apache.org/repos/asf/ambari/blob/00a4991e/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
new file mode 100644
index 0000000..b54b935
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
@@ -0,0 +1,84 @@
+/**
+ * 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.orm.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+@Singleton
+public class GroupDAO {
+ @Inject
+ Provider<EntityManager> entityManagerProvider;
+ @Inject
+ DaoUtils daoUtils;
+
+ @RequiresSession
+ public GroupEntity findByPK(Integer groupPK) {
+ return entityManagerProvider.get().find(GroupEntity.class, groupPK);
+ }
+
+ @RequiresSession
+ public List<GroupEntity> findAll() {
+ final TypedQuery<GroupEntity> query = entityManagerProvider.get().createQuery("SELECT group_entity FROM GroupEntity group_entity", GroupEntity.class);
+ return daoUtils.selectList(query);
+ }
+
+ @RequiresSession
+ public GroupEntity findGroupByName(String groupName) {
+ final TypedQuery<GroupEntity> query = entityManagerProvider.get().createNamedQuery("groupByName", GroupEntity.class);
+ query.setParameter("groupname", groupName.toLowerCase());
+ try {
+ return query.getSingleResult();
+ } catch (NoResultException e) {
+ return null;
+ }
+ }
+
+ @Transactional
+ public void create(GroupEntity group) {
+ group.setGroupName(group.getGroupName().toLowerCase());
+ entityManagerProvider.get().persist(group);
+ }
+
+ @Transactional
+ public GroupEntity merge(GroupEntity group) {
+ group.setGroupName(group.getGroupName().toLowerCase());
+ return entityManagerProvider.get().merge(group);
+ }
+
+ @Transactional
+ public void remove(GroupEntity group) {
+ entityManagerProvider.get().remove(merge(group));
+ }
+
+ @Transactional
+ public void removeByPK(Integer groupPK) {
+ remove(findByPK(groupPK));
+ }
+}