Beispiel #1
0
 /**
  * @test
  * @functional
  */
 public function testComplex()
 {
     $user = $this->getUser();
     $environment = $this->getEnvironment();
     $fictionController = new ApiController();
     /* @var $farm Farm */
     $farm = static::createEntity(new Farm(), ['changedById' => $user->getId(), 'name' => "{$this->uuid}-farm", 'comments' => "{$this->uuid}-description", 'envId' => $environment->id, 'accountId' => $user->getAccountId(), 'ownerId' => $user->getId()]);
     /* @var $roles EntityIterator */
     /* @var $role Role */
     $roles = Role::findByName('base-ubuntu1404');
     if (empty($roles) || !count($roles)) {
         $this->markTestSkipped("Not found suitable role, required role - 'base-ubuntu1404'");
     } else {
         $role = $roles->current();
     }
     //test Governance
     $this->getGovernance();
     /* @var $vpcList VpcList */
     $vpcList = \Scalr::getContainer()->aws(self::TEST_REGION, $this->getEnvironment())->ec2->vpc->describe(self::TEST_VPC_ID);
     /* @var  $vpc VpcData */
     $vpc = $vpcList->current();
     /* @var  $subnetList SubnetList */
     $subnetList = \Scalr::getContainer()->aws(self::TEST_REGION, $this->getEnvironment())->ec2->subnet->describe(null, [['name' => SubnetFilterNameType::vpcId(), 'value' => $vpc->vpcId]]);
     /* @var  $subnet SubnetData */
     $subnet = $subnetList->current();
     //setup test governance
     $vpcId = $vpc->vpcId;
     $subnetId = $subnet->subnetId;
     $governanceConfiguration = [SERVER_PLATFORMS::EC2 => [Scalr_Governance::INSTANCE_TYPE => ['enabled' => true, 'limits' => ['value' => ['t1.micro', 't2.small', 't2.medium', 't2.large'], 'default' => ['t2.small']]], Scalr_Governance::AWS_VPC => ['enabled' => true, 'limits' => ['regions' => [self::TEST_REGION => ['default' => true, 'ids' => [$vpcId]]], 'ids' => [$vpcId => [$subnetId]]]]]];
     $this->setupGovernanceConfiguration($governanceConfiguration);
     //farm role data
     $data = ['role' => ['id' => $role->id], 'alias' => 't-ps', 'platform' => SERVER_PLATFORMS::EC2, 'placement' => ['placementConfigurationType' => FarmRoles::AWS_CLASSIC_PLACEMENT_CONFIGURATION, 'region' => static::TEST_REGION], 'scaling' => ['enabled' => true, 'minInstances' => 2, 'maxInstances' => 3], 'instance' => ['instanceConfigurationType' => FarmRoles::AWS_INSTANCE_CONFIGURATION, 'instanceType' => ['id' => 't1.micro']]];
     //create farmRole with wrong instance type
     $data['instance']['instanceType']['id'] = 'm1.small';
     $response = $this->postFarmRole($farm->id, $data);
     $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE);
     //Add AWS VPC settings
     $farm->settings[FarmSetting::EC2_VPC_ID] = $vpc->vpcId;
     $farm->settings[FarmSetting::EC2_VPC_REGION] = self::TEST_REGION;
     $farm->save();
     //create farm role with AwsClassicPlacementConfiguration
     $data['instance']['instanceType']['id'] = 't2.small';
     $response = $this->postFarmRole($farm->id, $data);
     $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_STRUCTURE);
     //create farm role with incorrect subnet
     $subnetList->next();
     /* @var  $incorrectSubnet SubnetData */
     $incorrectSubnet = $subnetList->current();
     $data['placement'] = ['region' => self::TEST_REGION, 'placementConfigurationType' => 'AwsVpcPlacementConfiguration', 'subnets' => [['id' => $incorrectSubnet->subnetId]]];
     $response = $this->postFarmRole($farm->id, $data);
     $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE);
     //create farm role with incorrect region
     $data['placement'] = ['region' => Aws::REGION_US_WEST_1, 'placementConfigurationType' => 'AwsVpcPlacementConfiguration', 'subnets' => [['id' => $subnetId]]];
     $response = $this->postFarmRole($farm->id, $data);
     $this->assertErrorMessageContains($response, 400, ErrorMessage::ERR_INVALID_VALUE);
     //post farm role correct data
     $data['placement']['region'] = self::TEST_REGION;
     $data['alias'] = 't-ps-1';
     $response = $this->postFarmRole($farm->id, $data);
     $this->assertEquals(201, $response->status, $this->printResponseError($response));
     $farmRoleId = $response->getBody()->data->id;
     /* @var $farmRole FarmRole */
     $farmRole = FarmRole::findPk($farmRoleId);
     $this->assertNotEmpty($farmRole);
     $this->farmRoleToDelete($farmRoleId);
     $data['scaling']['rules'] = [];
     $this->assertObjectEqualsEntity($data, $farmRole);
     //Reset AWS VPC settings
     $farm->settings[FarmSetting::EC2_VPC_ID] = null;
     $farm->settings[FarmSetting::EC2_VPC_REGION] = null;
     $farm->save();
     //set default governance settings
     $this->restoreGovernanceConfiguration();
     //test farm roles post
     $data = ['role' => ['id' => $role->id], 'alias' => 't-ps-2', 'platform' => SERVER_PLATFORMS::EC2, 'placement' => ['placementConfigurationType' => FarmRoles::AWS_CLASSIC_PLACEMENT_CONFIGURATION, 'region' => static::TEST_REGION], 'scaling' => ['enabled' => true, 'minInstances' => 2, 'maxInstances' => 3], 'instance' => ['instanceConfigurationType' => FarmRoles::AWS_INSTANCE_CONFIGURATION, 'instanceType' => ['id' => 't1.micro']]];
     $response = $this->postFarmRole($farm->id, $data);
     $this->assertEquals(201, $response->status, $this->printResponseError($response));
     $farmRoleId = $response->getBody()->data->id;
     /* @var $farmRole FarmRole */
     $farmRole = FarmRole::findPk($farmRoleId);
     $this->assertNotEmpty($farmRole);
     $this->farmRoleToDelete($farmRoleId);
     $data['placement']['availabilityZones'] = '';
     $data['scaling']['rules'] = [];
     $this->assertObjectEqualsEntity($data, $farmRole);
     //test farm role modify scaling
     $data = ['scaling' => ['enabled' => false]];
     $response = $this->modifyFarmRole($farmRole->id, $data);
     $this->assertEquals(200, $response->status, $this->printResponseError($response));
     $farmRoleData = $response->getBody()->data;
     $this->assertObjectHasAttribute('scaling', $farmRoleData);
     $scalingConfiguration = $farmRoleData->scaling;
     $this->assertObjectNotHasAttribute('enabled', $scalingConfiguration);
     //test modify instance
     $data = ['instance' => ['instanceConfigurationType' => FarmRoles::AWS_INSTANCE_CONFIGURATION, 'instanceType' => 'm3.medium']];
     $response = $this->modifyFarmRole($farmRole->id, $data);
     $this->assertEquals(200, $response->status, $this->printResponseError($response));
     $farmRoleData = $response->getBody()->data;
     $this->assertObjectHasAttribute('instance', $farmRoleData);
     $instanceConfiguration = $farmRoleData->instance;
     $this->assertObjectHasAttribute('instanceType', $instanceConfiguration);
     $instanceType = $instanceConfiguration->instanceType;
     $this->assertObjectHasAttribute('id', $instanceType);
     $this->assertEquals('m3.medium', $instanceType->id);
     //test list farm roles filters
     $farmRoles = $this->listFarmRoles($farm->id);
     $farmRoleAdapter = $this->getAdapter('farmRole');
     $filterable = $farmRoleAdapter->getRules()[ApiEntityAdapter::RULE_TYPE_FILTERABLE];
     /* @var $farmRole FarmRole */
     foreach ($farmRoles as $farmRole) {
         foreach ($filterable as $property) {
             $filterValue = $farmRole->{$property};
             $listResult = $this->listFarmRoles($farm->id, [$property => $filterValue]);
             if (!static::isRecursivelyEmpty($filterValue)) {
                 foreach ($listResult as $filtered) {
                     $this->assertEquals($filterValue, $filtered->{$property}, "Property '{$property}' mismatch");
                 }
             }
         }
         $response = $this->getFarmRole($farmRole->id);
         $this->assertEquals(200, $response->status, $this->printResponseError($response));
         $dbFarmRole = FarmRole::findPk($farmRole->id);
         $this->assertObjectEqualsEntity($response->getBody()->data, $dbFarmRole, $farmRoleAdapter);
     }
 }
Beispiel #2
0
 /**
  * Get FarmRole entity
  *
  * @return FarmRole|null
  */
 public function getFarmRole()
 {
     if (empty($this->_farmRole) && !empty($this->farmRoleId)) {
         $this->_farmRole = FarmRole::findPk($this->farmRoleId);
     }
     return $this->_farmRole;
 }
Beispiel #3
0
 /**
  * Gets specified Farm Role taking into account both scope and authentication token
  *
  * @param   string  $farmRoleId          Numeric identifier of the Farm role
  * @param   int     $farmId     optional Identifier of the Farm containing Farm role
  * @param   bool    $modify     optional Flag checking write permissions
  *
  * @return  FarmRole    Returns the Script Entity on success
  * @throws  ApiErrorException
  */
 public function getFarmRole($farmRoleId, $farmId = null, $modify = false)
 {
     /* @var $role FarmRole */
     $role = FarmRole::findPk($farmRoleId);
     if (!$role) {
         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Requested Farm Role either does not exist or is not owned by your environment.");
     }
     if (isset($farmId)) {
         if ($role->farmId != $farmId) {
             throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid identifier of the farm");
         }
     } else {
         $farmId = $role->farmId;
     }
     $this->getFarm($farmId, $modify);
     if (!$this->hasPermissions($role, $modify)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
     return $role;
 }
Beispiel #4
0
 /**
  * @param   string      $platform       Name of platform
  * @param   string      $instanceId     The identifier of the cloud instance
  * @param   int         $farmRoleId     The identifier of farmRole
  * @param   JsonData    $tags           Additional tags
  * @throws  Exception
  */
 public function xImportAction($platform, $instanceId, $farmRoleId, JsonData $tags)
 {
     if (!in_array($platform, $this->allowedPlatforms)) {
         throw new Exception(sprintf("Platform '%s' is not supported", $platform));
     }
     if (!$this->environment->isPlatformEnabled($platform)) {
         throw new Exception(sprintf("Platform '%s' is not enabled", $platform));
     }
     if (empty($instanceId)) {
         throw new Exception('InstanceId cannot be empty');
     }
     /* @var $farmRole Entity\FarmRole */
     if (!$farmRoleId || !($farmRole = Entity\FarmRole::findPk($farmRoleId))) {
         throw new Exception('FarmRole was not found');
     }
     $this->request->checkPermissions($farmRole, true);
     $this->request->checkPermissions($farmRole->getFarm(), Acl::PERM_FARMS_UPDATE);
     $this->request->checkPermissions($farmRole->getFarm(), Acl::PERM_FARMS_SERVERS);
     $farmRole->settings[Entity\FarmRoleSetting::SCALING_ENABLED] = 0;
     $farmRole->settings->save();
     $farmRole->getServerImport($this->getUser())->import($instanceId, (array) $tags);
     $this->response->success();
 }
Beispiel #5
0
 /**
  * @return Image
  */
 public function createImageEntity()
 {
     $snapshot = $this->getSnapshotDetails();
     $envId = $this->envId;
     /* @var Entity\Server $server */
     $server = Entity\Server::findOneByServerId($this->serverId);
     if (!empty($server->farmRoleId)) {
         /* @var Entity\FarmRole $farmRole */
         $farmRole = Entity\FarmRole::findPk($server->farmRoleId);
         if (!empty($farmRole->roleId)) {
             /* @var Entity\Role $role */
             $role = Entity\Role::findPk($farmRole->roleId);
             $envId = $role->getScope() == ScopeInterface::SCOPE_ACCOUNT ? NULL : $envId;
         }
     }
     $image = new Image();
     $image->id = $this->snapshotId;
     $image->accountId = $this->clientId;
     $image->envId = $envId;
     $image->bundleTaskId = $this->id;
     $image->platform = $this->platform;
     $image->cloudLocation = $this->cloudLocation;
     $image->createdById = $this->createdById;
     $image->createdByEmail = $this->createdByEmail;
     $image->architecture = is_null($snapshot['os']->arch) ? 'x86_64' : $snapshot['os']->arch;
     $image->source = Image::SOURCE_BUNDLE_TASK;
     $image->status = Image::STATUS_ACTIVE;
     $image->agentVersion = $snapshot['szr_version'];
     $image->checkImage();
     if (!$image->name) {
         $image->name = $this->roleName . '-' . date('YmdHi');
     }
     $image->osId = $this->osId;
     $image->save();
     if ($snapshot['software']) {
         $software = [];
         foreach ((array) $snapshot['software'] as $soft) {
             $software[$soft->name] = $soft->version;
         }
         $image->setSoftware($software);
     }
     return $image;
 }
Beispiel #6
0
 /**
  * {@inheritdoc}
  * @see ApiEntityAdapter::validateEntity()
  */
 public function validateEntity($entity)
 {
     if (!$entity instanceof FarmRole) {
         throw new InvalidArgumentException(sprintf("First argument must be instance of Scalr\\Model\\Entity\\FarmRole class"));
     }
     if ($entity->id !== null) {
         if (!FarmRole::findPk($entity->id)) {
             throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf("Could not find out the Farm with ID: %d", $entity->id));
         }
     }
     if (empty($entity->farmId)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property farm.id");
     } else {
         $farm = $this->controller->getFarm($entity->farmId, true);
     }
     if (empty($entity->roleId)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property role.id");
     }
     if (empty($entity->platform)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property platform");
     }
     switch ($entity->platform) {
         case SERVER_PLATFORMS::EC2:
             if (empty($entity->settings[FarmRoleSetting::AWS_INSTANCE_TYPE])) {
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Missed property instance.type");
             }
             /* @var $platform Ec2PlatformModule */
             $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2);
             if (!in_array($entity->settings[FarmRoleSetting::AWS_INSTANCE_TYPE], $platform->getInstanceTypes())) {
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Wrong instance type");
             }
             $gov = new Scalr_Governance($this->controller->getEnvironment()->id);
             $allowGovernanceIns = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_INSTANCE_TYPE);
             if (isset($allowGovernanceIns) && !in_array($entity->settings[FarmRoleSetting::AWS_INSTANCE_TYPE], $allowGovernanceIns)) {
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, sprintf("Only %s %s allowed according to governance settings", ...count($allowGovernanceIns) > 1 ? [implode(', ', $allowGovernanceIns), 'instances are'] : [array_shift($allowGovernanceIns), 'instance is']));
             }
             if (!in_array($entity->cloudLocation, Aws::getCloudLocations())) {
                 throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Unknown region");
             }
             $vpcGovernanceRegions = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_VPC, 'regions');
             if (isset($vpcGovernanceRegions) && !array_key_exists($entity->cloudLocation, $vpcGovernanceRegions)) {
                 $regions = array_keys($vpcGovernanceRegions);
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, sprintf("Only %s %s allowed according to governance settings", ...count($regions) > 1 ? [implode(', ', $regions), 'regions are'] : [array_shift($regions), 'region is']));
             }
             $env = Scalr_Environment::init()->loadById($this->controller->getEnvironment()->id);
             $aws = $this->controller->getContainer()->aws($entity->cloudLocation, $env);
             if (!empty($entity->settings[FarmRoleSetting::AWS_AVAIL_ZONE]) && $entity->settings[FarmRoleSetting::AWS_AVAIL_ZONE] !== 'x-scalr-diff') {
                 $availZones = explode(":", str_replace("x-scalr-custom=", '', $entity->settings[FarmRoleSetting::AWS_AVAIL_ZONE]));
                 $ec2availabilityZones = [];
                 foreach ($aws->ec2->availabilityZone->describe() as $zone) {
                     /* @var $zone AvailabilityZoneData */
                     if (stristr($zone->zoneState, 'available')) {
                         $ec2availabilityZones[] = $zone->zoneName;
                     }
                 }
                 $diffZones = array_diff($availZones, $ec2availabilityZones);
                 if (!empty($diffZones)) {
                     throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf('%s %s available. Available zones are %s', ...count($diffZones) > 1 ? [implode(', ', $diffZones), 'zones are not', implode(', ', $ec2availabilityZones)] : [array_shift($diffZones), 'zone is not', implode(', ', $ec2availabilityZones)]));
                 }
             }
             if (!empty($entity->settings[FarmRoleSetting::AWS_VPC_SUBNET_ID])) {
                 $vpcId = $farm->settings[FarmSetting::EC2_VPC_ID];
                 $subnets = $platform->listSubnets($env, $entity->cloudLocation, $vpcId, true);
                 $vpcGovernanceIds = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_VPC, 'ids');
                 $subnetType = null;
                 foreach (json_decode($entity->settings[FarmRoleSetting::AWS_VPC_SUBNET_ID]) as $subnetId) {
                     $found = false;
                     foreach ($subnets as $subnet) {
                         if ($subnet['id'] == $subnetId) {
                             if ($subnetType == null) {
                                 $subnetType = $subnet['type'];
                             } else {
                                 if ($subnet['type'] != $subnetType) {
                                     throw new ApiErrorException(409, ErrorMessage::ERR_UNICITY_VIOLATION, "All subnets must be a same type");
                                 }
                             }
                             //check governance subnet settings
                             if (isset($vpcGovernanceIds[$vpcId])) {
                                 if (!empty($vpcGovernanceIds[$vpcId]) && is_array($vpcGovernanceIds[$vpcId]) && !in_array($subnetId, $vpcGovernanceIds[$vpcId])) {
                                     throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, sprintf("Only %s %s allowed by governance settings", ...count($vpcGovernanceIds[$vpcId]) > 1 ? [implode(', ', $vpcGovernanceIds[$vpcId]), 'subnets are'] : [array_shift($vpcGovernanceIds[$vpcId]), 'subnet is']));
                                 } elseif ($vpcGovernanceIds[$vpcId] == "outbound-only" && $subnetType != 'private') {
                                     throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Only private subnets allowed by governance settings");
                                 } elseif ($vpcGovernanceIds[$vpcId] == "full" && $subnetType != 'public') {
                                     throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Only public subnets allowed by governance settings");
                                 }
                             }
                             $found = true;
                         }
                     }
                     if (!$found) {
                         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Subnet with id '{$subnetId}' not found");
                     }
                 }
                 if (!empty($entity->settings[Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID])) {
                     $router = $this->controller->getFarmRole($entity->settings[Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID]);
                     if (empty($router->settings[Scalr_Role_Behavior_Router::ROLE_VPC_NID])) {
                         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Farm-role with id '{$router->id}' is not a valid router");
                     }
                 } else {
                     if ($subnetType == 'private') {
                         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "You must describe a VPC Router");
                     }
                 }
             } else {
                 if ($farm->settings[FarmSetting::EC2_VPC_ID]) {
                     throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "VPC Subnet(s) should be described");
                 }
             }
             break;
         default:
             if (in_array($entity->platform, SERVER_PLATFORMS::GetList())) {
                 throw new ApiErrorException(501, ErrorMessage::ERR_NOT_IMPLEMENTED, "Platform '{$entity->platform}' is not supported yet");
             } else {
                 throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Unknown platform '{$entity->platform}'");
             }
     }
     if (!$this->controller->hasPermissions($entity, true)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
 }
Beispiel #7
0
 /**
  * {@inheritdoc}
  * @see ApiEntityAdapter::validateEntity()
  */
 public function validateEntity($entity)
 {
     if (!$entity instanceof FarmRole) {
         throw new InvalidArgumentException(sprintf("First argument must be instance of Scalr\\Model\\Entity\\FarmRole class"));
     }
     if ($entity->id !== null) {
         if (!FarmRole::findPk($entity->id)) {
             throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf("Could not find out the Farm with ID: %d", $entity->id));
         }
     }
     if (empty($entity->farmId)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property farm.id");
     } else {
         /* @var  $farm Farm */
         $farm = $this->controller->getFarm($entity->farmId, true);
     }
     if (empty($entity->alias)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property alias");
     }
     if (!preg_match("/^[[:alnum:]](?:-*[[:alnum:]])*\$/", $entity->alias)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Alias should start and end with letter or number and contain only letters, numbers and dashes.");
     }
     if (empty($entity->roleId)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property role.id");
     }
     $roleBehaviors = $entity->getRole()->getBehaviors();
     $uniqueBehaviors = array_intersect($roleBehaviors, array_merge(...array_values(static::$uniqueFarmBehaviors)));
     if (!empty($uniqueBehaviors)) {
         //farm can include only one mysql or percona role
         if (array_intersect($uniqueBehaviors, static::$uniqueFarmBehaviors[ROLE_BEHAVIORS::MYSQL])) {
             $uniqueBehaviors = array_merge($uniqueBehaviors, array_diff(static::$uniqueFarmBehaviors[ROLE_BEHAVIORS::MYSQL], $uniqueBehaviors));
         }
         $farmRoleEntity = new FarmRole();
         $roleEntity = new Role();
         /* @var $conflicts EntityIterator */
         $conflicts = Role::find([AbstractEntity::STMT_FROM => "{$roleEntity->table()} JOIN {$farmRoleEntity->table('fr')} ON {$farmRoleEntity->columnRoleId('fr')} = {$roleEntity->columnId()}", AbstractEntity::STMT_WHERE => "{$farmRoleEntity->columnFarmId('fr')} = {$farmRoleEntity->qstr('farmId', $entity->farmId)} " . (empty($entity->id) ? '' : " AND {$farmRoleEntity->columnId('fr')} <> {$farmRoleEntity->qstr('id', $entity->id)}"), ['behaviors' => ['$regex' => implode('|', $uniqueBehaviors)]]]);
         if ($conflicts->count() > 0) {
             $conflictedBehaviors = [];
             /* @var  $role Role */
             foreach ($conflicts as $role) {
                 $conflictedBehaviors = array_merge($conflictedBehaviors, array_intersect($uniqueBehaviors, $role->getBehaviors()));
             }
             if (!empty(array_intersect($conflictedBehaviors, static::$uniqueFarmBehaviors[ROLE_BEHAVIORS::MYSQL]))) {
                 $conflictedBehaviors = array_diff($conflictedBehaviors, static::$uniqueFarmBehaviors[ROLE_BEHAVIORS::MYSQL]);
                 $conflictedBehaviors[] = 'mysql/percona';
             }
             $conflictedBehaviors = RoleAdapter::behaviorsToData($conflictedBehaviors);
             throw new ApiErrorException(409, ErrorMessage::ERR_UNICITY_VIOLATION, sprintf('Only one [%s] role can be added to farm', implode(', ', $conflictedBehaviors)));
         }
     }
     if (empty($entity->platform)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property platform");
     }
     switch ($entity->platform) {
         case SERVER_PLATFORMS::EC2:
             if (empty($entity->settings[FarmRoleSetting::INSTANCE_TYPE])) {
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Missed property instance.type");
             }
             /* @var $platform Ec2PlatformModule */
             $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2);
             if (!in_array($entity->settings[FarmRoleSetting::INSTANCE_TYPE], $platform->getInstanceTypes())) {
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Wrong instance type");
             }
             $gov = new Scalr_Governance($this->controller->getEnvironment()->id);
             $allowGovernanceIns = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::INSTANCE_TYPE);
             if (isset($allowGovernanceIns) && !in_array($entity->settings[FarmRoleSetting::INSTANCE_TYPE], $allowGovernanceIns)) {
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, sprintf("Only %s %s allowed according to governance settings", ...count($allowGovernanceIns) > 1 ? [implode(', ', $allowGovernanceIns), 'instances are'] : [array_shift($allowGovernanceIns), 'instance is']));
             }
             if (!in_array($entity->cloudLocation, Aws::getCloudLocations())) {
                 throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Unknown region");
             }
             $vpcGovernanceRegions = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_VPC, 'regions');
             if (isset($vpcGovernanceRegions) && !array_key_exists($entity->cloudLocation, $vpcGovernanceRegions)) {
                 $regions = array_keys($vpcGovernanceRegions);
                 throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, sprintf("Only %s %s allowed according to governance settings", ...count($regions) > 1 ? [implode(', ', $regions), 'regions are'] : [array_shift($regions), 'region is']));
             }
             $env = Scalr_Environment::init()->loadById($this->controller->getEnvironment()->id);
             $aws = $this->controller->getContainer()->aws($entity->cloudLocation, $env);
             if (!empty($entity->settings[FarmRoleSetting::AWS_AVAIL_ZONE]) && $entity->settings[FarmRoleSetting::AWS_AVAIL_ZONE] !== 'x-scalr-diff') {
                 $availZones = explode(":", str_replace("x-scalr-custom=", '', $entity->settings[FarmRoleSetting::AWS_AVAIL_ZONE]));
                 $ec2availabilityZones = [];
                 foreach ($aws->ec2->availabilityZone->describe() as $zone) {
                     /* @var $zone AvailabilityZoneData */
                     if (stristr($zone->zoneState, 'available')) {
                         $ec2availabilityZones[] = $zone->zoneName;
                     }
                 }
                 $diffZones = array_diff($availZones, $ec2availabilityZones);
                 if (!empty($diffZones)) {
                     throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf('%s %s available. Available zones are %s', ...count($diffZones) > 1 ? [implode(', ', $diffZones), 'zones are not', implode(', ', $ec2availabilityZones)] : [array_shift($diffZones), 'zone is not', implode(', ', $ec2availabilityZones)]));
                 }
             }
             if (!empty($farm->settings[FarmSetting::EC2_VPC_ID])) {
                 if (empty($entity->settings[FarmRoleSetting::AWS_VPC_SUBNET_ID])) {
                     throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "VPC Subnet(s) should be described");
                 }
                 $vpcId = $farm->settings[FarmSetting::EC2_VPC_ID];
                 $subnets = $platform->listSubnets($env, $entity->cloudLocation, $vpcId, true);
                 $vpcGovernanceIds = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_VPC, 'ids');
                 $subnetType = null;
                 foreach (json_decode($entity->settings[FarmRoleSetting::AWS_VPC_SUBNET_ID]) as $subnetId) {
                     $found = false;
                     foreach ($subnets as $subnet) {
                         if ($subnet['id'] == $subnetId) {
                             if ($subnetType == null) {
                                 $subnetType = $subnet['type'];
                             } else {
                                 if ($subnet['type'] != $subnetType) {
                                     throw new ApiErrorException(409, ErrorMessage::ERR_UNICITY_VIOLATION, "All subnets must be a same type");
                                 }
                             }
                             //check governance subnet settings
                             if (isset($vpcGovernanceIds[$vpcId])) {
                                 if (!empty($vpcGovernanceIds[$vpcId]) && is_array($vpcGovernanceIds[$vpcId]) && !in_array($subnetId, $vpcGovernanceIds[$vpcId])) {
                                     throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, sprintf("Only %s %s allowed by governance settings", ...count($vpcGovernanceIds[$vpcId]) > 1 ? [implode(', ', $vpcGovernanceIds[$vpcId]), 'subnets are'] : [array_shift($vpcGovernanceIds[$vpcId]), 'subnet is']));
                                 } else {
                                     if ($vpcGovernanceIds[$vpcId] == "outbound-only" && $subnetType != 'private') {
                                         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Only private subnets allowed by governance settings");
                                     } else {
                                         if ($vpcGovernanceIds[$vpcId] == "full" && $subnetType != 'public') {
                                             throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Only public subnets allowed by governance settings");
                                         }
                                     }
                                 }
                             }
                             $found = true;
                         }
                     }
                     if (!$found) {
                         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Subnet with id '{$subnetId}' not found");
                     }
                 }
                 if (!empty($entity->settings[Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID])) {
                     $router = $this->controller->getFarmRole($entity->settings[Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID]);
                     if (empty($router->settings[Scalr_Role_Behavior_Router::ROLE_VPC_NID])) {
                         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Farm-role with id '{$router->id}' is not a valid router");
                     }
                 } else {
                     if (\Scalr::config('scalr.instances_connection_policy') != 'local' && $subnetType == 'private') {
                         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "You must describe a VPC Router");
                     }
                 }
             }
             break;
         default:
             if (isset(SERVER_PLATFORMS::GetList()[$entity->platform])) {
                 throw new ApiErrorException(501, ErrorMessage::ERR_NOT_IMPLEMENTED, "Platform '{$entity->platform}' is not supported yet");
             } else {
                 throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Unknown platform '{$entity->platform}'");
             }
     }
     if (!$this->controller->hasPermissions($entity, true)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
 }
Beispiel #8
0
 /**
  * {@inheritdoc}
  * @see OrchestrationRule::hasAccessPermissions()
  */
 public function hasAccessPermissions($user, $environment = null, $modify = null)
 {
     return FarmRole::findPk($this->farmRoleId)->hasAccessPermissions($user, $environment, $modify);
 }