mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 01:32:18 +02:00
CLOUDSTACK-3049: Implemented role update for account. (#3058)
This commit is contained in:
parent
97ddd8dffd
commit
d68712eb7b
@ -16,6 +16,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
cloudstack/tools/docker/Dockerfile
|
cloudstack/tools/docker/Dockerfile
|
||||||
|
cloudstack/tools/docker/Dockerfile.smokedev
|
||||||
.dockerignore
|
.dockerignore
|
||||||
.idea
|
.idea
|
||||||
.git
|
.git
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.response.RoleResponse;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||||
@ -48,16 +49,19 @@ public class UpdateAccountCmd extends BaseCmd {
|
|||||||
//////////////// API parameters /////////////////////
|
//////////////// API parameters /////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ACL(accessType = AccessType.OperateEntry)
|
@ACL(accessType = AccessType.OperateEntry)
|
||||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account id")
|
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the current account name")
|
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Current account name")
|
||||||
private String accountName;
|
private String accountName;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "the ID of the domain where the account exists")
|
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "The UUID of the domain where the account exists")
|
||||||
private Long domainId;
|
private Long domainId;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.NEW_NAME, type = CommandType.STRING, required = true, description = "new name for the account")
|
@Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "The UUID of the dynamic role to set for the account")
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.NEW_NAME, type = CommandType.STRING, description = "New name for the account")
|
||||||
private String newName;
|
private String newName;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.NETWORK_DOMAIN,
|
@Parameter(name = ApiConstants.NETWORK_DOMAIN,
|
||||||
@ -65,7 +69,7 @@ public class UpdateAccountCmd extends BaseCmd {
|
|||||||
description = "Network domain for the account's networks; empty string will update domainName with NULL value")
|
description = "Network domain for the account's networks; empty string will update domainName with NULL value")
|
||||||
private String networkDomain;
|
private String networkDomain;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters")
|
@Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "Details for the account used to store specific parameters")
|
||||||
private Map details;
|
private Map details;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -87,6 +91,8 @@ public class UpdateAccountCmd extends BaseCmd {
|
|||||||
return domainId;
|
return domainId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getRoleId() { return roleId; }
|
||||||
|
|
||||||
public String getNewName() {
|
public String getNewName() {
|
||||||
return newName;
|
return newName;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,8 +37,10 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.cloudstack.acl.ControlledEntity;
|
import org.apache.cloudstack.acl.ControlledEntity;
|
||||||
import org.apache.cloudstack.acl.QuerySelector;
|
import org.apache.cloudstack.acl.QuerySelector;
|
||||||
|
import org.apache.cloudstack.acl.Role;
|
||||||
import org.apache.cloudstack.acl.RoleType;
|
import org.apache.cloudstack.acl.RoleType;
|
||||||
import org.apache.cloudstack.acl.SecurityChecker;
|
import org.apache.cloudstack.acl.SecurityChecker;
|
||||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||||
@ -1019,8 +1021,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
@DB
|
@DB
|
||||||
@ActionEvents({@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
|
@ActionEvents({@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
|
@ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")})
|
||||||
public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, final String timezone, String accountName,
|
public UserAccount createUserAccount(final String userName, final String password, final String firstName,
|
||||||
final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map<String, String> details, String accountUUID, final String userUUID,
|
final String lastName, final String email, final String timezone,
|
||||||
|
String accountName, final short accountType, final Long roleId, Long domainId,
|
||||||
|
final String networkDomain, final Map<String, String> details,
|
||||||
|
String accountUUID, final String userUUID,
|
||||||
final User.Source source) {
|
final User.Source source) {
|
||||||
|
|
||||||
if (accountName == null) {
|
if (accountName == null) {
|
||||||
@ -1155,7 +1160,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
UserVO user = retrieveAndValidateUser(updateUserCmd);
|
UserVO user = retrieveAndValidateUser(updateUserCmd);
|
||||||
s_logger.debug("Updating user with Id: " + user.getUuid());
|
s_logger.debug("Updating user with Id: " + user.getUuid());
|
||||||
|
|
||||||
validateAndUpdatApiAndSecretKeyIfNeeded(updateUserCmd, user);
|
validateAndUpdateApiAndSecretKeyIfNeeded(updateUserCmd, user);
|
||||||
Account account = retrieveAndValidateAccount(user);
|
Account account = retrieveAndValidateAccount(user);
|
||||||
|
|
||||||
validateAndUpdateFirstNameIfNeeded(updateUserCmd, user);
|
validateAndUpdateFirstNameIfNeeded(updateUserCmd, user);
|
||||||
@ -1344,7 +1349,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
* <li>If a pair of keys is provided, we validate to see if there is an user already using the provided API key. If there is someone else using, we throw an {@link InvalidParameterValueException} because two users cannot have the same API key.
|
* <li>If a pair of keys is provided, we validate to see if there is an user already using the provided API key. If there is someone else using, we throw an {@link InvalidParameterValueException} because two users cannot have the same API key.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
protected void validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
|
protected void validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmd updateUserCmd, UserVO user) {
|
||||||
String apiKey = updateUserCmd.getApiKey();
|
String apiKey = updateUserCmd.getApiKey();
|
||||||
String secretKey = updateUserCmd.getSecretKey();
|
String secretKey = updateUserCmd.getSecretKey();
|
||||||
|
|
||||||
@ -1687,6 +1692,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
public AccountVO updateAccount(UpdateAccountCmd cmd) {
|
public AccountVO updateAccount(UpdateAccountCmd cmd) {
|
||||||
Long accountId = cmd.getId();
|
Long accountId = cmd.getId();
|
||||||
Long domainId = cmd.getDomainId();
|
Long domainId = cmd.getDomainId();
|
||||||
|
Long roleId = cmd.getRoleId();
|
||||||
String accountName = cmd.getAccountName();
|
String accountName = cmd.getAccountName();
|
||||||
String newAccountName = cmd.getNewName();
|
String newAccountName = cmd.getNewName();
|
||||||
String networkDomain = cmd.getNetworkDomain();
|
String networkDomain = cmd.getNetworkDomain();
|
||||||
@ -1700,6 +1706,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
account = _accountDao.findEnabledAccount(accountName, domainId);
|
account = _accountDao.findEnabledAccount(accountName, domainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final AccountVO acctForUpdate = _accountDao.findById(account.getId());
|
||||||
|
|
||||||
// Check if account exists
|
// Check if account exists
|
||||||
if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
|
if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
|
||||||
s_logger.error("Unable to find account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
|
s_logger.error("Unable to find account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
|
||||||
@ -1712,25 +1720,48 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if user performing the action is allowed to modify this account
|
// Check if user performing the action is allowed to modify this account
|
||||||
checkAccess(getCurrentCallingAccount(), _domainMgr.getDomain(account.getDomainId()));
|
Account caller = getCurrentCallingAccount();
|
||||||
|
checkAccess(caller, _domainMgr.getDomain(account.getDomainId()));
|
||||||
|
|
||||||
// check if the given account name is unique in this domain for updating
|
if(newAccountName != null) {
|
||||||
Account duplicateAcccount = _accountDao.findActiveAccount(newAccountName, domainId);
|
|
||||||
if (duplicateAcccount != null && duplicateAcccount.getId() != account.getId()) {
|
if (newAccountName.isEmpty()) {
|
||||||
throw new InvalidParameterValueException(
|
throw new InvalidParameterValueException("The new account name for account '" + account.getUuid() + "' " +
|
||||||
"There already exists an account with the name:" + newAccountName + " in the domain:" + domainId + " with existing account id:" + duplicateAcccount.getId());
|
"within domain '" + domainId + "' is empty string. Account will be not renamed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the new proposed account name is absent in the domain
|
||||||
|
Account existingAccount = _accountDao.findActiveAccount(newAccountName, domainId);
|
||||||
|
if (existingAccount != null && existingAccount.getId() != account.getId()) {
|
||||||
|
throw new InvalidParameterValueException("The account with the proposed name '" +
|
||||||
|
newAccountName + "' exists in the domain '" +
|
||||||
|
domainId + "' with existing account id '" + existingAccount.getId() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
acctForUpdate.setAccountName(newAccountName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkDomain != null && !networkDomain.isEmpty()) {
|
if (networkDomain != null && !networkDomain.isEmpty()) {
|
||||||
if (!NetUtils.verifyDomainName(networkDomain)) {
|
if (!NetUtils.verifyDomainName(networkDomain)) {
|
||||||
throw new InvalidParameterValueException(
|
throw new InvalidParameterValueException("Invalid network domain or format. " +
|
||||||
"Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
|
"Total length shouldn't exceed 190 chars. Every domain part must be between 1 and 63 " +
|
||||||
|
"characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
|
||||||
+ "and the hyphen ('-'); can't start or end with \"-\"");
|
+ "and the hyphen ('-'); can't start or end with \"-\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final AccountVO acctForUpdate = _accountDao.findById(account.getId());
|
|
||||||
acctForUpdate.setAccountName(newAccountName);
|
if (roleId != null) {
|
||||||
|
final List<Role> roles = cmd.roleService.listRoles();
|
||||||
|
final boolean roleNotFound = roles.stream().filter(r -> r.getId() == roleId).count() == 0;
|
||||||
|
if (roleNotFound) {
|
||||||
|
throw new InvalidParameterValueException("Role with ID '" + roleId.toString() + "' " +
|
||||||
|
"is not found or not available for the account '" + account.getUuid() + "' " +
|
||||||
|
"in the domain '" + domainId + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
acctForUpdate.setRoleId(roleId);
|
||||||
|
}
|
||||||
|
|
||||||
if (networkDomain != null) {
|
if (networkDomain != null) {
|
||||||
if (networkDomain.isEmpty()) {
|
if (networkDomain.isEmpty()) {
|
||||||
@ -1741,17 +1772,14 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Account accountFinal = account;
|
final Account accountFinal = account;
|
||||||
success = Transaction.execute(new TransactionCallback<Boolean>() {
|
success = Transaction.execute((TransactionCallback<Boolean>) status -> {
|
||||||
@Override
|
boolean success1 = _accountDao.update(accountFinal.getId(), acctForUpdate);
|
||||||
public Boolean doInTransaction(TransactionStatus status) {
|
|
||||||
boolean success = _accountDao.update(accountFinal.getId(), acctForUpdate);
|
|
||||||
|
|
||||||
if (details != null && success) {
|
if (details != null && success1) {
|
||||||
_accountDetailsDao.update(accountFinal.getId(), details);
|
_accountDetailsDao.update(accountFinal.getId(), details);
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return success1;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
|||||||
@ -226,7 +226,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
|
|
||||||
private void prepareMockAndExecuteUpdateUserTest(int numberOfExpectedCallsForSetEmailAndSetTimeZone) {
|
private void prepareMockAndExecuteUpdateUserTest(int numberOfExpectedCallsForSetEmailAndSetTimeZone) {
|
||||||
Mockito.doReturn(userVoMock).when(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
|
Mockito.doReturn(userVoMock).when(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
|
||||||
Mockito.doNothing().when(accountManagerImpl).validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
Mockito.doNothing().when(accountManagerImpl).validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
Mockito.doReturn(accountMock).when(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
|
Mockito.doReturn(accountMock).when(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
|
||||||
|
|
||||||
Mockito.doNothing().when(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
|
Mockito.doNothing().when(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
@ -242,7 +242,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
InOrder inOrder = Mockito.inOrder(userVoMock, accountManagerImpl, userDaoMock, userAccountDaoMock);
|
InOrder inOrder = Mockito.inOrder(userVoMock, accountManagerImpl, userDaoMock, userAccountDaoMock);
|
||||||
|
|
||||||
inOrder.verify(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
|
inOrder.verify(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
|
||||||
inOrder.verify(accountManagerImpl).validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
inOrder.verify(accountManagerImpl).validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
inOrder.verify(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
|
inOrder.verify(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
|
||||||
|
|
||||||
inOrder.verify(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
|
inOrder.verify(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
@ -275,7 +275,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateAndUpdatApiAndSecretKeyIfNeededTestNoKeys() {
|
public void validateAndUpdatApiAndSecretKeyIfNeededTestNoKeys() {
|
||||||
accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
|
|
||||||
Mockito.verify(accountDaoMock, Mockito.times(0)).findUserAccountByApiKey(Mockito.anyString());
|
Mockito.verify(accountDaoMock, Mockito.times(0)).findUserAccountByApiKey(Mockito.anyString());
|
||||||
}
|
}
|
||||||
@ -284,14 +284,14 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
public void validateAndUpdatApiAndSecretKeyIfNeededTestOnlyApiKeyInformed() {
|
public void validateAndUpdatApiAndSecretKeyIfNeededTestOnlyApiKeyInformed() {
|
||||||
Mockito.doReturn("apiKey").when(UpdateUserCmdMock).getApiKey();
|
Mockito.doReturn("apiKey").when(UpdateUserCmdMock).getApiKey();
|
||||||
|
|
||||||
accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidParameterValueException.class)
|
@Test(expected = InvalidParameterValueException.class)
|
||||||
public void validateAndUpdatApiAndSecretKeyIfNeededTestOnlySecretKeyInformed() {
|
public void validateAndUpdatApiAndSecretKeyIfNeededTestOnlySecretKeyInformed() {
|
||||||
Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();
|
Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();
|
||||||
|
|
||||||
accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidParameterValueException.class)
|
@Test(expected = InvalidParameterValueException.class)
|
||||||
@ -308,7 +308,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
|
Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
|
||||||
Mockito.doReturn(pairUserAccountMock).when(accountDaoMock).findUserAccountByApiKey(apiKey);
|
Mockito.doReturn(pairUserAccountMock).when(accountDaoMock).findUserAccountByApiKey(apiKey);
|
||||||
|
|
||||||
accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -327,7 +327,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
|
Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
|
||||||
Mockito.doReturn(pairUserAccountMock).when(accountDaoMock).findUserAccountByApiKey(apiKey);
|
Mockito.doReturn(pairUserAccountMock).when(accountDaoMock).findUserAccountByApiKey(apiKey);
|
||||||
|
|
||||||
accountManagerImpl.validateAndUpdatApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
|
||||||
|
|
||||||
Mockito.verify(accountDaoMock).findUserAccountByApiKey(apiKey);
|
Mockito.verify(accountDaoMock).findUserAccountByApiKey(apiKey);
|
||||||
Mockito.verify(userVoMock).setApiKey(apiKey);
|
Mockito.verify(userVoMock).setApiKey(apiKey);
|
||||||
|
|||||||
@ -30,7 +30,7 @@ from marvin.lib.base import (Domain,
|
|||||||
User,
|
User,
|
||||||
NATRule,
|
NATRule,
|
||||||
Template,
|
Template,
|
||||||
PublicIPAddress)
|
PublicIPAddress, Role)
|
||||||
from marvin.lib.common import (get_domain,
|
from marvin.lib.common import (get_domain,
|
||||||
get_zone,
|
get_zone,
|
||||||
get_test_template,
|
get_test_template,
|
||||||
@ -67,6 +67,11 @@ class Services:
|
|||||||
# username
|
# username
|
||||||
"password": "fr3sca",
|
"password": "fr3sca",
|
||||||
},
|
},
|
||||||
|
"role": {
|
||||||
|
"name": "MarvinFake Role",
|
||||||
|
"type": "User",
|
||||||
|
"description": "Fake Role created by Marvin test"
|
||||||
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"email": "user@test.com",
|
"email": "user@test.com",
|
||||||
"firstname": "User",
|
"firstname": "User",
|
||||||
@ -261,6 +266,53 @@ class TestAccounts(cloudstackTestCase):
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@attr(tags=["advanced", "basic", "eip", "advancedns", "sg"],
|
||||||
|
required_hardware="false")
|
||||||
|
def test_02_update_account(self):
|
||||||
|
"""
|
||||||
|
Tests that accounts can be updated with new name, network domain, dynamic role
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
dynamic_roles_active = self.apiclient.listCapabilities(listCapabilities.listCapabilitiesCmd()).dynamicrolesenabled
|
||||||
|
if not dynamic_roles_active:
|
||||||
|
self.skipTest("Dynamic Role-Based API checker not enabled, skipping test")
|
||||||
|
|
||||||
|
ts = str(time.time())
|
||||||
|
network_domain = 'mycloud.com'
|
||||||
|
|
||||||
|
account = Account.create(self.apiclient, self.services['account'])
|
||||||
|
self.cleanup.append(account)
|
||||||
|
|
||||||
|
role = Role.create(self.apiclient, self.services['role'])
|
||||||
|
self.cleanup.append(role)
|
||||||
|
|
||||||
|
account.update(self.apiclient, newname=account.name + ts)
|
||||||
|
account.update(self.apiclient, roleid=role.id)
|
||||||
|
account.update(self.apiclient, networkdomain=network_domain)
|
||||||
|
|
||||||
|
list_accounts_response = list_accounts(self.apiclient, id=account.id)
|
||||||
|
test_account = list_accounts_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
test_account.roleid, role.id,
|
||||||
|
"Check the role for the account is changed")
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
test_account.networkdomain, network_domain,
|
||||||
|
"Check the domain for the account is changed")
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
test_account.name, account.name + ts,
|
||||||
|
"Check the name for the account is changed")
|
||||||
|
|
||||||
|
try:
|
||||||
|
account.update(self.apiclient, newname="")
|
||||||
|
self.fail("Account name change to empty name succeeded. Must be error.")
|
||||||
|
except CloudstackAPIException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestRemoveUserFromAccount(cloudstackTestCase):
|
class TestRemoveUserFromAccount(cloudstackTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
143
tools/docker/Dockerfile.smokedev
Normal file
143
tools/docker/Dockerfile.smokedev
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# CloudStack-simulator build
|
||||||
|
|
||||||
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
|
MAINTAINER "Apache CloudStack" <dev@cloudstack.apache.org>
|
||||||
|
LABEL Vendor="Apache.org" License="ApacheV2" Version="4.12.0-SNAPSHOT"
|
||||||
|
|
||||||
|
RUN apt-get -y update && apt-get install -y \
|
||||||
|
genisoimage \
|
||||||
|
libffi-dev \
|
||||||
|
libssl-dev \
|
||||||
|
git \
|
||||||
|
sudo \
|
||||||
|
ipmitool \
|
||||||
|
maven \
|
||||||
|
openjdk-8-jdk \
|
||||||
|
python-dev \
|
||||||
|
python-setuptools \
|
||||||
|
python-pip \
|
||||||
|
python-mysql.connector \
|
||||||
|
supervisor \
|
||||||
|
python-crypto \
|
||||||
|
python-openssl
|
||||||
|
|
||||||
|
RUN echo 'mysql-server mysql-server/root_password password root' | debconf-set-selections; \
|
||||||
|
echo 'mysql-server mysql-server/root_password_again password root' | debconf-set-selections;
|
||||||
|
|
||||||
|
RUN apt-get install -qqy mysql-server && \
|
||||||
|
apt-get clean all && \
|
||||||
|
mkdir /var/run/mysqld; \
|
||||||
|
chown mysql /var/run/mysqld
|
||||||
|
|
||||||
|
#
|
||||||
|
# this package is needed if one wants to run marvin tests from
|
||||||
|
# inside the running simulator.
|
||||||
|
#
|
||||||
|
RUN pip install pyOpenSSL
|
||||||
|
|
||||||
|
RUN echo '''sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"''' >> /etc/mysql/mysql.conf.d/mysqld.cnf
|
||||||
|
RUN (/usr/bin/mysqld_safe &); sleep 5; mysqladmin -u root -proot password ''
|
||||||
|
|
||||||
|
COPY agent /root/agent
|
||||||
|
COPY api /root/api
|
||||||
|
COPY build /root/build
|
||||||
|
COPY client /root/client
|
||||||
|
COPY cloud-cli /root/cloud-cli
|
||||||
|
COPY cloudstack.iml /root/cloudstack.iml
|
||||||
|
COPY core /root/core
|
||||||
|
COPY debian /root/debian
|
||||||
|
COPY deps /root/deps
|
||||||
|
COPY developer /root/developer
|
||||||
|
COPY engine /root/engine
|
||||||
|
COPY framework /root/framework
|
||||||
|
COPY LICENSE.header /root/LICENSE.header
|
||||||
|
COPY LICENSE /root/LICENSE
|
||||||
|
COPY maven-standard /root/maven-standard
|
||||||
|
COPY NOTICE /root/NOTICE
|
||||||
|
COPY packaging /root/packaging
|
||||||
|
COPY plugins /root/plugins
|
||||||
|
COPY pom.xml /root/pom.xml
|
||||||
|
COPY python /root/python
|
||||||
|
COPY quickcloud /root/quickcloud
|
||||||
|
COPY requirements.txt /root/requirements.txt
|
||||||
|
COPY scripts /root/scripts
|
||||||
|
COPY server /root/server
|
||||||
|
COPY services /root/services
|
||||||
|
COPY setup /root/setup
|
||||||
|
COPY systemvm /root/systemvm
|
||||||
|
COPY target /root/target
|
||||||
|
COPY test/bindirbak /root/test/bindirbak
|
||||||
|
COPY test/conf /root/test/conf
|
||||||
|
COPY test/metadata /root/test/metadata
|
||||||
|
COPY test/pom.xml /root/test/pom.xml
|
||||||
|
COPY test/scripts /root/test/scripts
|
||||||
|
COPY test/selenium /root/test/selenium
|
||||||
|
COPY test/systemvm /root/test/systemvm
|
||||||
|
COPY test/target /root/test/target
|
||||||
|
COPY tools/pom.xml /root/tools/pom.xml
|
||||||
|
COPY tools/apidoc /root/tools/apidoc
|
||||||
|
COPY tools/checkstyle /root/tools/checkstyle
|
||||||
|
COPY tools/devcloud4/pom.xml /root/tools/devcloud4/pom.xml
|
||||||
|
COPY tools/devcloud-kvm/pom.xml /root/tools/devcloud-kvm/pom.xml
|
||||||
|
COPY tools/marvin/pom.xml /root/tools/marvin/pom.xml
|
||||||
|
COPY tools/pom.xml /root/tools/pom.xml
|
||||||
|
COPY ui /root/ui
|
||||||
|
COPY usage /root/usage
|
||||||
|
COPY utils /root/utils
|
||||||
|
COPY vmware-base /root/vmware-base
|
||||||
|
|
||||||
|
RUN cd /root && mvn -Pdeveloper -Dsimulator -DskipTests -pl "!:cloud-marvin" install
|
||||||
|
|
||||||
|
RUN (/usr/bin/mysqld_safe &) && \
|
||||||
|
sleep 5 && \
|
||||||
|
cd /root && \
|
||||||
|
mvn -Pdeveloper -pl developer -Ddeploydb && \
|
||||||
|
mvn -Pdeveloper -pl developer -Ddeploydb-simulator
|
||||||
|
|
||||||
|
COPY tools/marvin /root/tools/marvin
|
||||||
|
COPY tools/docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
COPY tools/docker/docker_run_tests.sh /root
|
||||||
|
|
||||||
|
RUN cd /root && mvn -Pdeveloper -Dsimulator -DskipTests -pl ":cloud-marvin"
|
||||||
|
|
||||||
|
RUN MARVIN_FILE=`find /root/tools/marvin/dist/ -name "Marvin*.tar.gz"` && pip install $MARVIN_FILE
|
||||||
|
|
||||||
|
COPY test/integration /root/test/integration
|
||||||
|
COPY tools /root/tools
|
||||||
|
|
||||||
|
RUN pip install --upgrade pyOpenSSL
|
||||||
|
|
||||||
|
EXPOSE 8080 8096
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
CMD ["/usr/bin/supervisord"]
|
||||||
|
|
||||||
|
# --------------------------------
|
||||||
|
#
|
||||||
|
# docker run -v ~/dev/tmp:/tmp -v ~/IdeaProjects/cloudstack/test/integration/smoke:/root/test/integration/smoke -it
|
||||||
|
# --name simulator -p 8080:8080 -p8096:8096 simulator:4.12
|
||||||
|
#
|
||||||
|
# docker exec -it simulator bash
|
||||||
|
#
|
||||||
|
# cat /root/docker_run_tests.sh
|
||||||
|
# for instructions
|
||||||
|
#
|
||||||
50
tools/docker/docker_run_tests.sh
Normal file
50
tools/docker/docker_run_tests.sh
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
MODE=${1:-advanced}
|
||||||
|
SUITE=${2:-smoke}
|
||||||
|
|
||||||
|
export MARVIN_CONFIG=setup/dev/$MODE.cfg
|
||||||
|
export TEST_SUITE=test/integration/$SUITE
|
||||||
|
export ZONE_NAME=Sandbox-simulator
|
||||||
|
|
||||||
|
cd /root
|
||||||
|
|
||||||
|
python tools/marvin/marvin/deployDataCenter.py -i setup/dev/$MODE.cfg
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
RUN WHOLE '$SUITE' SUITE
|
||||||
|
--------------------------
|
||||||
|
nosetests-2.7 \
|
||||||
|
--with-marvin \
|
||||||
|
--marvin-config=${MARVIN_CONFIG} \
|
||||||
|
-w ${TEST_SUITE} \
|
||||||
|
--with-xunit \
|
||||||
|
--xunit-file=/tmp/bvt_selfservice_cases.xml \
|
||||||
|
--zone=${ZONE_NAME} \
|
||||||
|
--hypervisor=simulator \
|
||||||
|
-a tags=$MODE,required_hardware=false
|
||||||
|
--------------------------
|
||||||
|
OR INDIVIDUAL TEST LIKE
|
||||||
|
--------------------------
|
||||||
|
nosetests-2.7 -s --with-marvin --marvin-config=${MARVIN_CONFIG} --zone=${ZONE_NAME} \
|
||||||
|
--hypervisor=simulator -a tags=$MODE,required_hardware=false \
|
||||||
|
test/integration/smoke/test_accounts.py:TestAccounts
|
||||||
|
--------------------------
|
||||||
|
EOF
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user