Upload
philip-norton
View
3.297
Download
2
Tags:
Embed Size (px)
DESCRIPTION
The configuration management system in Drupal 8 seems like a great idea, but what is it? In this session I hope to show what configuration management is, why it is needed and how it will make all of our lives as Drupal site builders better.
Citation preview
Drupal 8Configuration Management
Phil Norton Drupal Camp Yorkshire 2014
DrupalCamp Yorkshire 2014
Me
• Phil Norton (@philipnorton42)
• #! code (www.hashbangcode.com)
• Technical Lead at Access
• Help run NWDUG
What Is Drupal Config?
!A quick quiz
Blog post
Permissions
Vocabulary
Taxonomy term
Field definition
Menu
Variable
Menu item
User
Contents of a block
Configuration Content
Blog Post !Taxonomy Term !Menu Item !Block Content
Permissions !
Field Definition !
Vocabulary !
Menu !
Variable
TAC !
Webform !
Default Content
!Views
Configuration Content
Blog Post !Taxonomy Term !Menu Item !Block Content
Permissions !
Field Definition !
Vocabulary !
Menu !
Variable
TAC !
Webform !
Default Content
!Views
Content !!
Session !!
State !!
Configuration
An article page, uploaded files
Logged in status, shopping carts
Last cron run
Everything else
Challenge• Developer:
• Wants to work on code
• Wants to change the config
• Wants to deploy across environments
• Client:
• Wants to work on content
• Doesn’t want to lose work
Current Situation
Drupal 7 Configuration
• Features
• Install/Update hooks
• Install Profiles
How do we currently manage configuration in Drupal?
Features• Export and import of certain configurations as
modules
• Not all modules supported so there tends to be gaps in the configuration
• Adding Features support for modules is not easy
• Features ‘Overridden’ sadness
Install/Update Hooks
• Create tables
• Set up variables
• Fill in ‘gaps’ in Features modules
Install Profiles
• Combine Features modules and install hooks
• Full site setup out of the box
• Limited Drupal API available
• Doesn’t always work as planned
What’s Next In Drupal 8?
Drupal 8 Initiatives• Configuration Management
• Web Services
• Multilingual
• HTML 5
• Mobile
CMIConfiguration Management Initiative
http://bit.ly/1tDBbsA !
http://drupal8cmi.org
CMI• Lead by Greg Dunlap - (heyrocker)
Also involved are:
• Joel Farris (senpai)
• Jonathan Lambert (jlambert)
• David Strauss (davidstrauss)
• Larry Garfield (crell)
• Karoly Negeyesi (chx)
• Angie Byron (webchick)
• Alex Pott (alexpott)
• And many others…
CMI
To build Drupal from the ground up to be better at configuration management
CMI• Move configuration management into core
• Allow storage of configuration in files
• Allow the transfer of configuration between environments
• Create an API to allow custom configurations
• Integrate UUID into core so certain configurations can be given machine names
Usage
Behind The Scenes
• Active configuration is stored in the database
• Clicking Export collates the configuration that each module defines and combines it with the current active configuration
• Export contains the active configuration in the form of YAML files
Behind The Scenes• YAML files are used to store the configuration
• A ‘staging’ and an ‘active’ directory are defined in settings.php
• Used to store and compare the current configuration
• By default the directories are stored in the location /sites/default/files/config_<hash>/
active
• Originally intended to be used as the location of the active configuration
• Active configuration is now stored in the database
• Configuration development module (https://drupal.org/project/config_devel)
staging
• Stores current imported configuration as YAML files
• Shows difference between configuration changes
• Changes made here can be imported into active configuration
YAML!YAML Ain't Markup Language
!(Yet Another Markup Language)
YAML• Data orientated format
• Has several benefits over other formats like INI, JSON, XML
• Support for hierarchical values
• Lists and associative arrays possible
• Used extensively in Drupal 8
YAML• Simple values defined by
key: value
• Hierarchical values defined with whitespace
keys: key1: value key2: value
YAML
Comments start the line with a ‘#’
!
# This is a comment item: value
YAML Lists!- item1 - item2 - item3 !![item1, item2, item3] !!- {name: 'webserver1', ip: ‘192.168.100.100’} - {name: 'webserver2', ip: ‘192.168.100.101’} - {name: 'webserver3', ip: ‘192.168.100.102’}
uuid: ''name: Drupalmail: ''slogan: ''page: 403: '' 404: '' front: useradmin_compact_mode: falseweight_select_max: 100langcode: en
core/modules/system/config/install/system.site.yml
YAML Filenames In Drupal 8
• < module >.< component >.yml system.settings.yml views.settings.yml
• < module >.< component >.< entity >.yml image.style.medium.ymlviews.view.content.yml
Configuration API
Configuration Schema
• Needed to define what your configuration will hold
• Kwalify inspired format
• Used to define what types of data the configuration will contain
• See more at: https://drupal.org/node/1905070
system.schema.ymlsystem.site: type: mapping label: 'Site information' mapping: uuid: type: string label: 'Site UUID' name: type: label label: 'Site name' mail: type: email label: 'E-mail address' slogan: type: label label: 'Slogan' page: type: mapping label: 'Pages' mapping: 403: type: path label: 'Default 403 (access denied) page' 404: type: path label: 'Default 404 (not found) page' front: type: path label: 'Default front page' admin_compact_mode: type: boolean label: 'Compact mode' weight_select_max: type: integer label: 'Weight element maximum value' langcode: type: string label: 'Default language'
system.schema.yml
system.site: type: mapping label: 'Site information' mapping: uuid: type: string label: 'Site UUID' name: type: label label: 'Site name'
Schema name
Also shows the configuration
filename “system.site.yml”
Used to reference this configuration
system.schema.yml
system.site: type: mapping label: 'Site information' mapping: uuid: type: string label: 'Site UUID' name: type: label label: 'Site name'
Container data type
‘mapping’ is for key value sets
allows for associative arrays of different data
types
system.schema.yml
system.site: type: mapping label: 'Site information' mapping: uuid: type: string label: 'Site UUID' name: type: label label: 'Site name'
Label
Used as an interface label
system.schema.yml
system.site: type: mapping label: 'Site information' mapping: uuid: type: string label: 'Site UUID' name: type: label label: 'Site name'
Start of mapping section
item keyitem typeitem label
Simple Configuration• Can be single values or arrays of values
• Used to store global configuration options
• Easy to implement:
• Create schema YAML file in < module >/config/install/schema
• Create config YAML file < module >/config/install
Getting Configurationuuid: ''name: Drupalmail: ''slogan: ''page: 403: '' 404: '' front: useradmin_compact_mode: falseweight_select_max: 100langcode: en!!$config = \Drupal::config('system.site'); $email = $config->get('mail');
!$cofig = \Drupal::config(‘system.site')$page403 = $config->get('page.403');
Getting Configurationuuid: ''name: Drupalmail: ''slogan: ''page: 403: '' 404: '' front: useradmin_compact_mode: falseweight_select_max: 100langcode: en!!$email = \Drupal::config('system.site')->get('mail');
!$page403 = \Drupal::config('system.site')->get('page.403');
!
Setting Configuration$config = \Drupal::config('system.site'); $config->set(‘mail’, ‘[email protected]’); $config->save();
!!$config = \Drupal::config(‘system.site’)->set('mail', ‘[email protected]’); $config->save();!!\Drupal::config(‘system.site’)->set('mail', ‘[email protected])->save();
Clear Configuration
$config = \Drupal::config('system.site');$config->clear('mail')->save();
!\Drupal::config('system.site')->delete();
Configuration Entities
• Used to store custom entity configurations
• More complex and therefore harder to implement
• Used for configurations that have multiple entries Example: Views, Image cache settings, Contact form categories
Contact Category Interface
namespace Drupal\contact;!use Drupal\Core\Config\Entity\ConfigEntityInterface;!/** * Provides an interface defining a contact category entity. */interface CategoryInterface extends ConfigEntityInterface {!}
Contact Category Entitynamespace Drupal\contact\Entity;!use Drupal\Core\Config\Entity\ConfigEntityBase;use Drupal\Core\Entity\EntityStorageInterface;use Drupal\contact\CategoryInterface;!/** * Defines the contact category entity. * * @ConfigEntityType( * id = "contact_category", * label = @Translation("Contact category"), * controllers = { * "access" = "Drupal\contact\CategoryAccessController", * "list_builder" = "Drupal\contact\CategoryListBuilder", * "form" = { * "add" = "Drupal\contact\CategoryForm", * "edit" = "Drupal\contact\CategoryForm", * "delete" = "Drupal\contact\Form\CategoryDeleteForm" * } * }, * config_prefix = "category", * admin_permission = "administer contact forms", * bundle_of = "contact_message", * entity_keys = { * "id" = "id", * "label" = "label" * }, * links = { * "delete-form" = "contact.category_delete", * "edit-form" = "contact.category_edit" * } * ) */class Category extends ConfigEntityBase implements CategoryInterface {
class Category extends ConfigEntityBase implements CategoryInterface {! /** * The category ID. * * @var string */ public $id;! /** * The category label. * * @var string */ public $label;! /** * List of recipient e-mail addresses. * * @var array */ public $recipients = array();! /** * An auto-reply message to send to the message author. * * @var string */ public $reply = '';! /** * Weight of this category (used for sorting). * * @var int */ public $weight = 0;
contact.category.personal.ymlid: personallabel: 'Personal contact form'recipients: { }reply: ''weight: 0status: trueuuid: 43155e41-8a58-4264-ab00-be97a0736aa0langcode: endependencies: { }!!$contact_category = $this->entityManager() ->getStorage('contact_category') ->load('personal');!$contact_category->label();
contact.category.personal.ymlid: personallabel: 'Personal contact form'recipients: { }reply: ''weight: 0status: trueuuid: 43155e41-8a58-4264-ab00-be97a0736aa0langcode: endependencies: { }!!$config = \Drupal::config('contact.category.personal')->get();$label = $config['label'];!$label = \Drupal::config(‘contact.category.personal')->get('label');
Drush• Full Drush integration available
• Need Drush version 7.x
• Currently in dev branch of Drush
• List of Drush commands:http://www.drushcommands.com/drush-7x/config/config-list
Drush
Export config from the active configuration to the staging directory drush config-export drush cex
Drush
Import the staging configuration into the active configuration drush config-import drush cim
Workflow
• Staging config should become part of your codebase
• New configuration changes should be exported and integrated into code base
• Configuration in code should then be used to move configuration between servers
Dev Stage Live
export
deploy deploy
import import
Git
Config
Code
Git
Config
Code
Git
Config
Code
Workflow
Dev Stage Live
drush cex
deploy deploy
drush cim drush cim
Git
Config
Code
Git
Config
Code
Git
Config
Code
Drush Workflow
Roll Your Own Configurations
!!!!
Create a module that stores simple configurations
MyModule
• A module that integrates with the configuration management API
• Defines a single configuration item
• Defines a page to display the configuration
• Defines a form to change the configuration
MyModule Configuration• mymodule.info.yml file defines the module
• mymodule.settings.yml contains the module configuration
• mymodule.schema.yml contains information about the configuration item being defined
• mymodule.routing.yml defines routes to a page and a form
name: 'MyModule'type: moduledescription: 'My module'version: VERSIONcore: 8.x
mymodule.info.yml
configitem: ''
/config/install/mymodule.settings.yml
mymodule.settings: type: mapping label: 'My Module Settings' mapping: configitem: type: string label: 'A config item'
/config/schema/mymodule.schema.yml
mymodule.page: path: '/mymodule' defaults: _content: '\Drupal\mymodule\Controller\MyModuleController::description' requirements: _access: 'TRUE'!mymodule.admin: path: '/mymodule/edit' defaults: _form: '\Drupal\mymodule\Form\MyModuleAdminForm' requirements: _access: 'TRUE'
mymodule.routing.yml
MyModule Page
• mymodule.routing.yml defines the route to the page
• Destination MyModuleController::description() loads the configuration and displays it
namespace Drupal\mymodule\Controller;!use Drupal\Core\Controller\ControllerBase;!/** * Custom page. */class MyModuleController extends ControllerBase {! /** * An example page. * * @return string * A render array containing some page content. */ public function description() {! $mymodule_config = \Drupal::config('mymodule.settings');! $output = array();! $output['mymodule_output'] = array( '#markup' => t('The value of configitem is "!configitem"', array('!configitem' => $mymodule_config->get('configitem'))) );! return $output; }}
lib/Drupal/mymodule/Controller/MyModuleController.php
MyModule Form
• mymodule.routing.yml defines the route to the form
• Class MyModuleAdminForm defines a form that loads the configuration
• Configuration is saved upon submission of the form
namespace Drupal\mymodule\Form;!use Drupal\Core\Form\ConfigFormBase;!/** * Configure MyModule admin settings for this site. */class MyModuleAdminForm extends ConfigFormBase {! /** * Implements \Drupal\Core\Form\FormInterface::getFormID(). */ public function getFormID() { return 'mymodule_edit_form'; }! /** * Implements \Drupal\Core\Form\FormInterface::buildForm(). */ public function buildForm(array $form, array &$form_state) { $config = $this->configFactory()->get('mymodule.settings');! $form['configitem'] = array( '#type' => 'textfield', '#title' => t('Config Settings'), '#default_value' => $config->get('configitem') );! return parent::buildForm($form, $form_state); }! /** * Implements \Drupal\Core\Form\FormInterface::submitForm(). */ public function submitForm(array &$form, array &$form_state) { $config = $this->configFactory()->get('mymodule.settings');! $config->set('configitem', $form_state['values']['configitem'])->save();! parent::submitForm($form, $form_state); }}
lib/Drupal/mymodule/Form/MyModuleAdminForm.php
! /** * Implements \Drupal\Core\Form\FormInterface::buildForm(). */ public function buildForm(array $form, array &$form_state) { $config = $this->configFactory()->get('mymodule.settings');! $form['configitem'] = array( '#type' => 'textfield', '#title' => t('Config Settings'), '#default_value' => $config->get('configitem') );! return parent::buildForm($form, $form_state); }
lib/Drupal/mymodule/Form/MyModuleAdminForm.php
!! /** * Implements \Drupal\Core\Form\FormInterface::submitForm(). */ public function submitForm(array &$form, array &$form_state) { $config = $this->configFactory()->get('mymodule.settings');! $config->set('configitem', $form_state['values']['configitem'])->save();! parent::submitForm($form, $form_state); }
lib/Drupal/mymodule/Form/MyModuleAdminForm.php
configitem: 'another value'
Drupal 7
• Configuration management has been back ported into Drupal 7
• Configuration Management module https://drupal.org/project/configuration
Resources• Creating Drupal 8.x modules
https://drupal.org/developing/modules/8
!• Configuration API in Drupal 8
https://drupal.org/node/1667894
!• Understanding Drupal 8's config entities
http://www.previousnext.com.au/blog/understanding-drupal-8s-config-entities
!• Configuration schema/metadata
https://drupal.org/node/1905070
!• Configuration inspector for Drupal 8
https://drupal.org/project/config_inspector
Drupal 8 CMI Needs You!
• Lots of work still needs to be done on CMI
• Go to http://drupal8cmi.org/ and pick an issue to work on
Me
• Phil Norton (@philipnorton42)
• #! code (www.hashbangcode.com)
• Technical Lead at Access
• Help run NWDUG