Skip to content
Snippets Groups Projects
Commit 8eb7930b authored by xiaohua guan's avatar xiaohua guan Committed by Yas Naoi
Browse files

Issue #3053038 by Xiaohua Guan, yas, baldwinlouie: Add configurations to...

Issue #3053038 by Xiaohua Guan, yas, baldwinlouie: Add configurations to enable/disable cost management features
parent 06b0043c
No related branches found
No related tags found
No related merge requests found
Showing
with 292 additions and 58 deletions
......@@ -675,6 +675,20 @@ function aws_cloud_update_8139() {
}
}
/**
* Add cost management configurations.
*/
function aws_cloud_update_8140() {
$config_factory = \Drupal::configFactory();
$config = $config_factory->getEditable('aws_cloud.settings');
$config->set('aws_cloud_instance_type_prices', TRUE);
$config->set('aws_cloud_instance_type_prices_spreadsheet', TRUE);
$config->set('aws_cloud_instance_type_cost', TRUE);
$config->set('aws_cloud_instance_type_cost_list', TRUE);
$config->set('aws_cloud_instance_list_cost_column', TRUE);
$config->save();
}
/**
* Helper function to add fields to the entity type.
*
......
......@@ -90,6 +90,15 @@ function aws_cloud_instance_type_allowed_values_function(FieldStorageConfig $def
$cloud_context = $entity->getCloudContext();
}
$instance_types = aws_cloud_get_instance_types($cloud_context);
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_type_cost') == FALSE) {
$instance_types_converted = [];
foreach ($instance_types as $id => $value) {
$instance_types_converted[$id] = explode(':', $value)[0];
}
$instance_types = $instance_types_converted;
}
}
}
catch (Exception $e) {
......@@ -460,6 +469,11 @@ EOF;
* The cloud config entity.
*/
function aws_cloud_create_or_update_pricing_spreadsheet(CloudConfig $cloud_config) {
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_type_prices_spreadsheet') == FALSE) {
return;
}
$url = $cloud_config->get('field_spreadsheet_pricing_url')->value;
if (empty($url)) {
// Find the existing spreadsheet created for other cloud config entities.
......@@ -934,18 +948,21 @@ function aws_cloud_form_cloud_server_template_aws_cloud_launch_form_alter(&$form
/* @var \Drupal\cloud\Entity\CloudServerTemplate $cloud_server_template */
$cloud_server_template = \Drupal::routeMatch()->getParameter('cloud_server_template');
$form['cost'] = [
'#type' => 'details',
'#title' => t('Cost'),
'#open' => TRUE,
];
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_type_cost_list')) {
$form['cost'] = [
'#type' => 'details',
'#title' => t('Cost'),
'#open' => TRUE,
];
$cloud_context = \Drupal::routeMatch()->getParameter('cloud_context');
$price_table_renderer = \Drupal::service('aws_cloud.instance_type_price_table_renderer');
$form['cost']['price_table'] = $price_table_renderer->render(
$cloud_context,
$cloud_server_template->get('field_instance_type')->value
);
$cloud_context = \Drupal::routeMatch()->getParameter('cloud_context');
$price_table_renderer = \Drupal::service('aws_cloud.instance_type_price_table_renderer');
$form['cost']['price_table'] = $price_table_renderer->render(
$cloud_context,
$cloud_server_template->get('field_instance_type')->value
);
}
$form['automation'] = [
'#type' => 'details',
......@@ -1113,6 +1130,10 @@ function aws_cloud_form_cloud_server_template_aws_cloud_form_common_alter(&$form
$form['#attached']['drupalSettings']['aws_cloud']['field_security_group_default_values']
= $security_group_default_values;
$config = \Drupal::config('aws_cloud.settings');
$form['#attached']['drupalSettings']['aws_cloud']['aws_cloud_instance_type_cost']
= $config->get('aws_cloud_instance_type_cost') == '1' ? TRUE : FALSE;
// Hide labels of field_tags.
$form['tags']['field_tags']['widget']['#title'] = NULL;
}
......@@ -2523,3 +2544,48 @@ function aws_cloud_get_views_items_options() {
100 => '100',
];
}
/**
* Implements hook_views_pre_view().
*/
function aws_cloud_views_pre_view($view, $display_id, array &$args) {
if ($view->id() === 'cloud_listing') {
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_type_prices') == FALSE) {
$view->removeHandler($display_id, 'field', 'pricing_internal_cloud_config');
}
if ($config->get('aws_cloud_instance_type_prices_spreadsheet') == FALSE) {
$view->removeHandler($display_id, 'field', 'pricing_external_cloud_config');
}
return;
}
if ($view->id() === 'aws_instances') {
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_list_cost_column') == FALSE) {
$view->removeHandler($display_id, 'field', 'cost');
}
}
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function aws_cloud_menu_local_tasks_alter(&$data, $route_name) {
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_type_prices') == FALSE) {
unset($data['tabs'][0]['aws_cloud.local_tasks.instance_type_price']);
}
}
/**
* Implements hook_menu_local_actions_alter().
*/
function aws_cloud_menu_local_actions_alter(&$local_actions) {
$config = \Drupal::config('aws_cloud.settings');
if ($config->get('aws_cloud_instance_type_prices') == FALSE) {
unset($local_actions['aws_cloud.instance_type_prices']);
}
}
......@@ -28,3 +28,8 @@ services:
aws_cloud.google_spreadsheet:
class: Drupal\aws_cloud\Service\GoogleSpreadsheetService
arguments: ['@messenger', '@config.factory', '@aws_cloud.instance_type_price_data_provider', '@string_translation']
aws_cloud.route_subscriber:
class: Drupal\aws_cloud\Routing\AwsCloudRouteSubscriber
tags:
- { name: event_subscriber }
......@@ -21,5 +21,10 @@ aws_cloud_volume_notification_hour: '09'
aws_cloud_volume_notification_minutes: '00'
aws_cloud_view_items_per_page: 50
aws_cloud_view_expose_items_per_page: true
aws_cloud_instance_type_prices: true
aws_cloud_instance_type_prices_spreadsheet: true
aws_cloud_instance_type_cost: true
aws_cloud_instance_type_cost_list: true
aws_cloud_instance_list_cost_column: true
google_credential_file_path: 'private://aws_cloud/.gapps/client_secrets.json'
google_credential_signature: ''
......@@ -17,6 +17,8 @@ aws_cloud.settings:
type: string
aws_cloud_mock_data:
type: string
aws_cloud_mock_instance_types:
type: string
aws_cloud_scheduler_tag:
type: string
aws_cloud_scheduler_periods:
......@@ -59,6 +61,16 @@ aws_cloud.settings:
type: integer
aws_cloud_view_expose_items_per_page:
type: boolean
aws_cloud_instance_type_prices:
type: boolean
aws_cloud_instance_type_prices_spreadsheet:
type: boolean
aws_cloud_instance_type_cost:
type: boolean
aws_cloud_instance_type_cost_list:
type: boolean
aws_cloud_instance_list_cost_column:
type: boolean
google_credential_file_path:
type: string
google_credential_signature:
......
......@@ -23,6 +23,12 @@
});
}
// Don't display cost information in the dropdown of instance type,
// if the configuration is false.
if (!drupalSettings.aws_cloud.aws_cloud_instance_type_cost) {
return;
}
// Select2 custom results adapter.
$.fn.select2.amd.define("CustomResultsAdapter", [
"select2/utils",
......
......@@ -9,6 +9,7 @@ use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\aws_cloud\Service\GoogleSpreadsheetService;
use Drupal\cloud\Plugin\CloudConfigPluginManagerInterface;
use Drupal\Core\Config\Config;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -393,20 +394,40 @@ class AwsCloudAdminSettings extends ConfigFormBase {
'#default_value' => $config->get('aws_cloud_scheduler_periods'),
];
$form['google'] = [
$form['cost_management'] = [
'#type' => 'details',
'#title' => $this->t('Cost Management'),
'#open' => TRUE,
];
$form['cost_management']['aws_cloud_instance_type_prices'] = [
'#type' => 'checkbox',
'#title' => $this->t('Instace Type Prices'),
'#description' => $this->t('Enable Instance Type Prices.'),
'#default_value' => $config->get('aws_cloud_instance_type_prices'),
];
$form['cost_management']['aws_cloud_instance_type_prices_spreadsheet'] = [
'#type' => 'checkbox',
'#title' => $this->t('Instace Type Prices Spreadsheet'),
'#description' => $this->t('Enable Instance Type Prices Spreadsheet.'),
'#default_value' => $config->get('aws_cloud_instance_type_prices_spreadsheet'),
];
$form['cost_management']['google'] = [
'#type' => 'details',
'#title' => $this->t('Google'),
'#open' => TRUE,
];
$form['google']['google_credential'] = [
$form['cost_management']['google']['google_credential'] = [
'#type' => 'textarea',
'#title' => $this->t('Google Credential'),
'#description' => $this->t("The credential data of a service account."),
'#rows' => 15,
];
$form['google']['google_credential_file_path'] = [
$form['cost_management']['google']['google_credential_file_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Google Credential File Path'),
'#description' => $this->t(
......@@ -416,6 +437,27 @@ class AwsCloudAdminSettings extends ConfigFormBase {
'#default_value' => $config->get('google_credential_file_path'),
];
$form['cost_management']['aws_cloud_instance_type_cost'] = [
'#type' => 'checkbox',
'#title' => $this->t('Instace Type Cost'),
'#description' => $this->t('Enable Instance Type Cost in Server Template New or Edit Form.'),
'#default_value' => $config->get('aws_cloud_instance_type_cost'),
];
$form['cost_management']['aws_cloud_instance_type_cost_list'] = [
'#type' => 'checkbox',
'#title' => $this->t('Instace Type Cost List'),
'#description' => $this->t('Enable Instance Type Cost List in Server Template Launch Form.'),
'#default_value' => $config->get('aws_cloud_instance_type_cost_list'),
];
$form['cost_management']['aws_cloud_instance_list_cost_column'] = [
'#type' => 'checkbox',
'#title' => $this->t('Instace List Cost Column'),
'#description' => $this->t('Enable Cost Column in Instance List.'),
'#default_value' => $config->get('aws_cloud_instance_list_cost_column'),
];
$form['#attached']['library'][] = 'aws_cloud/aws_cloud_view_builder';
return parent::buildForm($form, $form_state);
......@@ -426,14 +468,25 @@ class AwsCloudAdminSettings extends ConfigFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->configFactory()->getEditable('aws_cloud.settings');
$old_config = clone $config;
$form_state->cleanValues();
$views_settings = [];
$old_credential_file_path = $config->get('google_credential_file_path');
$excluded_keys = [];
if ($form_state->getValue('aws_cloud_instance_type_prices_spreadsheet') == FALSE) {
$excluded_keys[] = 'google_credential';
$excluded_keys[] = 'google_credential_file_path';
}
$instance_time = '';
$volume_time = '';
foreach ($form_state->getValues() as $key => $value) {
if (in_array($key, $excluded_keys)) {
continue;
}
if ($key == 'aws_cloud_view_items_per_page') {
$views_settings[$key] = (int) $value;
}
......@@ -490,11 +543,13 @@ class AwsCloudAdminSettings extends ConfigFormBase {
$config->save();
if (!empty($form_state->getValue('google_credential'))) {
$this->saveGoogleCredential(
$form_state->getValue('google_credential'),
$old_credential_file_path
);
if ($form_state->getValue('aws_cloud_instance_type_prices_spreadsheet') == TRUE) {
if (!empty($form_state->getValue('google_credential'))) {
$this->saveGoogleCredential(
$form_state->getValue('google_credential'),
$old_credential_file_path
);
}
}
if (!empty($views_settings)) {
......@@ -502,12 +557,21 @@ class AwsCloudAdminSettings extends ConfigFormBase {
}
parent::submitForm($form, $form_state);
if ($this->shouldCacheBeCleaned($old_config, $config)) {
drupal_flush_all_caches();
}
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
// Don't validate if the spreadsheet of instance type prices is disabled.
if ($form_state->getValue('aws_cloud_instance_type_prices_spreadsheet') == FALSE) {
return;
}
$google_credential = $form_state->getValue('google_credential');
if (empty($google_credential)) {
$credential_file_path = $form_state->getValue('google_credential_file_path');
......@@ -682,4 +746,33 @@ class AwsCloudAdminSettings extends ConfigFormBase {
return $cloud_configs_changed;
}
/**
* Judge whether cache should be cleaned or not.
*
* @param \Drupal\Core\Config\Config $old_config
* The old config object.
* @param \Drupal\Core\Config\Config $config
* The config object.
*
* @return bool
* Whether cache should be cleaned or not.
*/
private function shouldCacheBeCleaned(Config $old_config, Config $config) {
$items = [
'aws_cloud_instance_type_prices',
'aws_cloud_instance_type_prices_spreadsheet',
'aws_cloud_instance_type_cost',
'aws_cloud_instance_type_cost_list',
'aws_cloud_instance_list_cost_column',
];
foreach ($items as $item) {
if ($old_config->get($item) != $config->get($item)) {
return TRUE;
}
}
return FALSE;
}
}
<?php
namespace Drupal\aws_cloud\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
/**
* Listens to the dynamic route events.
*/
class AwsCloudRouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
if ($route = $collection->get('aws_cloud.instance_type_prices')) {
$config = \Drupal::config('aws_cloud.settings');
// If the configuration is false, the page can't be accessed.
if ($config->get('aws_cloud_instance_type_prices') == FALSE) {
$route->setRequirement('_access', 'FALSE');
}
}
}
}
......@@ -156,6 +156,13 @@ class AwsPricingService implements AwsPricingServiceInterface {
* {@inheritdoc}
*/
public function getInstanceTypes() {
$mock_data = $this->configFactory
->get('aws_cloud.settings')
->get('aws_cloud_mock_instance_types');
if ($this->dryRun && $mock_data) {
return json_decode($mock_data, TRUE);
}
// Give max memory for json decoding.
ini_set('memory_limit', '-1');
$instance_types = [];
......
......@@ -4,6 +4,7 @@ namespace Drupal\Tests\aws_cloud\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\Component\Utility\Random;
use Drupal\Tests\aws_cloud\Traits\AwsCloudTestTrait;
// Updated by yas 2016/06/02
// Updated by yas 2016/06/01
......@@ -24,6 +25,8 @@ use Drupal\Component\Utility\Random;
*/
class AwsCloudConfigTest extends BrowserTestBase {
use AwsCloudTestTrait;
const AWS_CLOUD_CONFIG_REPEAT_COUNT = 1;
/**
......@@ -57,7 +60,10 @@ class AwsCloudConfigTest extends BrowserTestBase {
}
$config = \Drupal::configFactory()->getEditable('aws_cloud.settings');
$config->set('aws_cloud_test_mode', TRUE);
$config->set('aws_cloud_test_mode', TRUE)
->save();
$this->initMockInstanceTypes();
$web_user = $this->drupalCreateUser([
'administer cloud config entities',
......
......@@ -6,7 +6,6 @@ use Drupal\Component\Serialization\Yaml;
use Drupal\Component\Utility\Random;
use Drupal\Tests\aws_cloud\Traits\AwsCloudTestTrait;
use Drupal\Tests\BrowserTestBase;
use Drupal\aws_cloud\Service\AwsPricingService;
use Drupal\aws_cloud\Service\GoogleSpreadsheetService;
/**
......@@ -40,18 +39,6 @@ abstract class AwsCloudTestCase extends BrowserTestBase {
protected $latestTemplateVars;
protected $instanceTypes = [
'm1.small' => 'm1.small:1:2:2:0.048:170:300',
'm1.medium' => 'm1.medium:1:3:3.75:0.096:340:600',
'm1.large' => 'm1.large:2:7:7.5:0.192:700:1200',
't1.micro' => 't1.micro:1:2:2:0.048:170:300',
't2.micro' => 't2.micro:1:2:2:0.048:170:300',
't3.micro' => 't3.micro:1:2:2:0.048:170:300',
'm1.xlarge' => 'm1.xlarge:2:7:7.5:0.384:1400:3000',
'm2.xlarge' => 'm2.xlarge:2:7:7.5:0.766:2800:6000',
'm3.xlarge' => 'm3.xlarge:2:7:7.5:1.5:6000:12000',
];
/**
* Set up test.
*/
......@@ -62,7 +49,11 @@ abstract class AwsCloudTestCase extends BrowserTestBase {
$this->random = new Random();
}
$this->initMockPricingService();
$config = \Drupal::configFactory()->getEditable('aws_cloud.settings');
$config->set('aws_cloud_test_mode', TRUE)
->save();
$this->initMockInstanceTypes();
$this->initMockGoogleSpreadsheetService();
$this->createCloudContext();
......@@ -146,27 +137,6 @@ abstract class AwsCloudTestCase extends BrowserTestBase {
$cloud->save();
}
/**
* Mock the AwsPricingService.
*
* The mock up will return an array of instances that matches up with the data
* returned from the pricing endpoint call.
*/
private function initMockPricingService() {
$mock_pricing_service = $this
->getMockBuilder(AwsPricingService::class)
->disableOriginalConstructor()
->getMock();
$mock_pricing_service->expects($this->any())
->method('getInstanceTypes')
->willReturn($this->instanceTypes);
// Provide a mock service container, for the services our module uses.
$container = \Drupal::getContainer();
$container->set('aws_cloud.pricing', $mock_pricing_service);
}
/**
* Mock the GoogleSpreadsheetService.
*
......@@ -203,8 +173,7 @@ abstract class AwsCloudTestCase extends BrowserTestBase {
}
$config = \Drupal::configFactory()->getEditable('aws_cloud.settings');
$config->set('aws_cloud_test_mode', TRUE)
->set('aws_cloud_mock_data', json_encode($mock_data))
$config->set('aws_cloud_mock_data', json_encode($mock_data))
->save();
}
......
......@@ -40,7 +40,7 @@ class InstanceTypePriceControllerTest extends AwsCloudTestCase {
$this->assertResponse(200);
$this->assertText(t('AWS Cloud Instance Type Prices'));
foreach ($this->instanceTypes as $instance_type_data) {
foreach (aws_cloud_get_instance_types($cloud_context) as $instance_type_data) {
$parts = explode(':', $instance_type_data);
$this->assertText($parts[0]);
}
......
......@@ -232,4 +232,28 @@ trait AwsCloudTestTrait {
return $entity;
}
/**
* Initialize mock instance types.
*
* The mock instance types will be saved to configuration
* aws_cloud_mock_instance_types.
*/
protected function initMockInstanceTypes() {
$mock_instance_types = [
'm1.small' => 'm1.small:1:2:2:0.048:170:300',
'm1.medium' => 'm1.medium:1:3:3.75:0.096:340:600',
'm1.large' => 'm1.large:2:7:7.5:0.192:700:1200',
't1.micro' => 't1.micro:1:2:2:0.048:170:300',
't2.micro' => 't2.micro:1:2:2:0.048:170:300',
't3.micro' => 't3.micro:1:2:2:0.048:170:300',
'm1.xlarge' => 'm1.xlarge:2:7:7.5:0.384:1400:3000',
'm2.xlarge' => 'm2.xlarge:2:7:7.5:0.766:2800:6000',
'm3.xlarge' => 'm3.xlarge:2:7:7.5:1.5:6000:12000',
];
$config = \Drupal::configFactory()->getEditable('aws_cloud.settings');
$config->set('aws_cloud_mock_instance_types', json_encode($mock_instance_types))
->save();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment