doc/plugins.md in power_stencil-0.4.22 vs doc/plugins.md in power_stencil-0.5.0
- old
+ new
@@ -8,10 +8,16 @@
- [Functional code growing](#functional-code-growing)
- [Need of very specific post actions developed in Ruby](#need-of-very-specific-post-actions-developed-in-ruby)
- [Enhance `power_stencil` command line](#enhance-power_stencil-command-line)
- [What are plugins ?](#what-are-plugins-)
- [Creating plugin local to the project](#creating-plugin-local-to-the-project)
+ - [Plugin creation](#plugin-creation)
+ - [Adding new subcommands to `PowerStencil`](#adding-new-subcommands-to-powerstencil)
+ - [Providing entity types and templates](#providing-entity-types-and-templates)
+ - [Providing custom build process](#providing-custom-build-process)
+- [Plugin capabilities and structure](#plugin-capabilities-and-structure)
+- [Conclusion](#conclusion)
<!-- /TOC -->
[:back:][Documentation root]
# Why plugins ?
@@ -47,12 +53,14 @@
:warning: Plugins provided as standalone Gems are not thoroughly tested, for the time being, you may use plugins local to the project.
# Creating plugin local to the project
-The is a command provided for that, that will create a whole plugin skeleton.
+## Plugin creation
+There is a command provided for that, that will create a whole plugin skeleton.
+
```shell
$ power_stencil plugin --create myplugin
Generated new plugin 'myplugin'
$ ll .ps_project/plugins/myplugin
@@ -79,21 +87,20 @@
So what was the impact on the project.
If you do a `power_stencil info` you see a new part appeared in the report
```
+
--------------------------------------------------------------------------------
Plugins:
--> Plugin 'myplugin' has following capabilities:
+ - config: true
- command_line: true
- - local_config: true
- processors: true
- - build: false
+ - build: true
- dsl: false
- entity_definitions: true
- - code: true
- - version: true
- templates: true
```
Each of the lines correspond to what is called a _plugin capability_.
You can get the same information by issuing:
@@ -109,25 +116,24 @@
$ power_stencil plugin --list -v
```
1 plugin found to be used in this project.
- - myplugin (in '/tmp/tst project/.ps_project/plugins/myplugin/lib/myplugin.rb')
+ - myplugin (in '/tmp/demo/.ps_project/plugins/myplugin/lib/myplugin.rb')
+ config: true
command_line: true
- local_config: true
processors: true
- build: false
+ build: true
dsl: false
entity_definitions: true
- code: true
- version: true
templates: true
```
-
-Obviously by default the plugin does nothing useful, yet it defined some placeholders. For example in the output here above it says `command_line: true`. What could it mean ?
+## Adding new subcommands to `PowerStencil`
+Obviously by default the plugin does nothing very useful, yet it defined some placeholders and demo entity type. For example in the output here above it says `command_line: true`. What could it mean ?
+
Let's try to see to help:
```shell
$ power_stencil --help
PowerStencil is the Swiss-army knife templating workflow for developers and ops.
@@ -165,33 +171,278 @@
Let's try it:
```shell
$ power_stencil myplugin
-MYPLUGIN PLUGIN WAZ HERE
+MYPLUGIN PLUGIN WAZ HERE !!
```
-Wow it worked ! Useless, but worked !
+Wow it worked ! Useless, but worked ! But it's a good demo on how to create your own subcommands in `PowerStencil`.
+## Providing entity types and templates
-The documentation for plugins is not yet done, so you are encouraged to read the code, the `capabilities` (in the output of `power_stencil info`) give you an idea of what plugins can do. Some official plugins are under development, and the documentation will be improved along their development...
+Of course you can provide new entity types and templates templates within plugin. The plugin created contains a demo entity type which brings its own template template (and even a custom build, but we will see that in next paragraph).
-**:warning: As opposed to the rest of `PowerStencil`, the functionnality is nevertheless not completely frozen. This will be the case once `PowerStencil` turns 1.0.0.**
+You can see in the output of `power_stencil info` (in _availaible entity types_) that a new entity type has been added to the project by the plugin: `myplugin_entity`
+```
+- Type 'myplugin_entity' --> Myplugin::EntityDefinitions::MypluginEntity (template-template path: '/tmp/demo/.ps_project/plugins/myplugin/etc/templates/myplugin_entity')
+```
+and you can see as well that it provides a template template.
+So let's create a new entity of this type...
+
+```
+$ power_stencil create myplugin_entity/test -v
+Creating new entity 'myplugin_entity/test'
+Entities analysis completed.
+Created 'myplugin_entity/test'
+```
+We can check the directory `myplugin_entity/test`, but actually a new entity has been created and provided some templates.
+
+we can check using `power_stencil check myplugin_entity/test`:
+
+```
+$ power_stencil check myplugin_entity/test
+ 'myplugin_entity/test':
+ - Storage path : '/tmp/demo/.ps_project/entities/myplugin_entity/test.yaml'
+ - Templates path : '/tmp/demo/myplugin_entity/test'
+ - Status : Valid
+ - Buildable : true
+```
+So it used the template templates to generate templates in `myplugin_entity/test`
+
+So far so good, we can provide entity types and templates from a plugin... :+1:
+
+## Providing custom build process
+
+As we can see in the previous output of `power_stencil check myplugin_entity/test`, the entity is said to be `buildable`. But to demonstrate the possiblity to define custom builds within a plugin this entity is defined to be buildable by the plugin, meaning that after the templates are rendered, the plugin is involved to perform some post process actions. How is it achieved ?
+
+First lets have a look at the entity type definition for `myplugin_entity`. `power_stencil info` shows that the class of the entity type is `Myplugin::EntityDefinitions::MypluginEntity` and we can find it in `.ps_project/plugins/myplugin/lib/myplugin/entity_definitions/myplugin_entity.rb`:
+
+```ruby
+module Myplugin
+ module EntityDefinitions
+
+ class MypluginEntity < PowerStencil::SystemEntityDefinitions::ProjectEntity
+
+ entity_type :myplugin_entity
+
+ buildable_by :myplugin
+
+ end
+
+ end
+end
+```
+
+Here we see a standard entity type definition how we already saw previously except that instead of the standard `buildable` directive, we find a `buildable_by :myplugin` directive. This is simply saying that the build for this entity type is delegated to the plugin `myplugin`.
+
+**:information_source: Entity types provided by plugins do not have to be built necessarily by the plugin they belong to !** Here the idea is just demonstrate the possibility to create custom builds.
+
+
+As a reminder the build process is the following:
+
+![simple-flow-image]
+
+When we talk about custom builds we actually talk about the last step. The core `PowerStencil` engine provides only one `buildable` entity which is the `simple_exec` entity type. And its [post-process] action was simply to call the script (main.sh) it generated.
+
+Here to demonstrate the possibility to create a custom build, the post-process action will simply display the template attached to `myplugin_entity` entity type.
+
+If we have a look in `myplugin_entity/test` we see it contains a template named `message.txt`, and its content is:
+
+```erb
+
+This message has been generated on the <%= Time.now %>
+This is an example of what you can do, and how much PowerStencil is customizable !
+
+This text is the result of a full build process of the entity '<%= build_target.as_path %>' by the plugin '<%= build_target.buildable_by %>'.
+
+```
+Ok, knowing that, let's finally build the `myplugin_entity/test` we created in the previous paragraph:
+
+```
+$ power_stencil build myplugin_entity/test
+
+This message has been generated on the 2019-10-24 18:37:46 +0200
+This is an example of what you can do, and how much PowerStencil is customizable !
+
+This text is the result of a full build process of the entity 'myplugin_entity/test' by the plugin 'myplugin'.
+
+ - 'myplugin_entity/test' has been correctly built
+```
+
+The last line is actually displayed by the build process, but see above that building the entity resulted in displaying the result of the _detemplatization_ ... So a post process actually occurred. Where does it come from ?
+
+We can find that in the main file of the plugin: `.ps_project/plugins/myplugin/lib/myplugin.rb`:
+
+```ruby
+require 'myplugin/version'
+require 'myplugin/plugin_helper'
+require 'myplugin/myplugin_processor'
+require 'myplugin/dsl/myplugin_dsl'
+
+module Myplugin
+
+ def self.post_build_hook(built_entity, generated_files_path)
+ # This is an example of what you could do after files are generated, ie pretty much anything...
+ case built_entity.type
+ when :myplugin_entity
+ generated_file = File.join generated_files_path, 'message.txt'
+ puts File.readlines(generated_file)
+ else
+ raise PowerStencil::Error, 'Plugin myplugin doesnt know how handle the build of a myplugin_entity entity type !'
+ end
+ end
+
+end
+```
+
+This is pretty self explanatory. It contains only one method named `self.post_build_hook` and it receives as parameter:
+
+* The entity you are building.
+* The path to where the templates have been _detemplatized_.
+
+:information_source: So it's really easy to implement whatever you want there and use information from both the entity itself and the generated files to implement something as complew as you want.
+
+Here the code simply reads the generated `message.txt` file and displays it...
+
+# Plugin capabilities and structure
+
+So the `power_stencil plugin --create` generated a fully working plugin, implementing all the features (actually for the time being only custom dsl is not yet implemented) you could define in a template.
+
+The generated plugin has the structure of a legit ruby gem, and this is not by chance, this is to prepare the fact that you may want to create a stand-alone plugin gem that you you may want to re-use in different projects.
+
+But this is not mandatory. Actually the only mandatory file for a plugin to be valid is the file `etc/plugin_capabilities.yaml` in the plugin directory. This file declares what the plugin is able to do. For the `myplugin` we just created it contains:
+
+```yaml
+---
+# This file defines the capabilities exposed by the plugin. This file is mandatory
+# for a plugin to be considered as valid.
+
+# Define the main module of the plugin. In this module you can define the build method
+# if the plugin exposes a build (actually a post build hook occurring after the files
+# are "detemplatized")
+:plugin_module: Myplugin
+
+# In the processors defined in the hereunder hash you map a subcommand with the processor
+# that will handle it. A plugin can define as many subcommands as needed, or none...
+# Hash keys should match sub-commands declared in the `command_line.yaml` file and processor
+# classes should expose an `execute` method.
+:processors:
+ myplugin: Myplugin::Processor
+
+# This is the name of the method called after the files are detemplatized. This method has
+# to be a module method in the `plugin_module` module.
+:build: post_build_hook
+
+# If a dsl module is declared it will be injected in the DSL available in the shell or templates
+:dsl: null
+
+# These are the files (array) defining entity types. These files should not be already
+# required by the plugin as they will be required by the framework when needed.
+:entity_definitions:
+ - myplugin/entity_definitions/myplugin_entity
+
+# A list of root directories where you can find templates in directories named from the
+# entity types they are attached to.
+:templates:
+ - etc/templates
+```
+
+As it is quite self-documented, I won't too much elaborate on the meaning of each of the fields. But actually a plugin can actually provide ... nothing.
+
+Let's create a plugin fully manually instead of using the `power_stencil plugin --create`. From the root of the project, let's create the directory:
+
+ $ mkdir -p .ps_project/plugins/minimal/etc
+
+(of course the command to create the directory may be different on your system). Then here let's create a `plugin_capabilities.yaml` file with the following content:
+
+```yaml
+---
+:plugin_module: null
+:processors: null
+:build: null
+:dsl: null
+:entity_definitions: null
+:templates: null
+```
+
+Bam ! We just created a more than useless yet valid plugin ! You can check that in the output of `power_stencil info`:
+
+```
+ --> Plugin 'minimal' has following capabilities:
+ - config: false
+ - command_line: false
+ - processors: false
+ - build: false
+ - dsl: false
+ - entity_definitions: false
+ - templates: false
+```
+
+All the code you may write has to be within the `lib` subdirectory, so let's create it:
+
+ $ mkdir -p .ps_project/plugins/minimal/lib
+
+And create there a file named `minimal_entity.rb` with the following content:
+
+```ruby
+class Minimal < PowerStencil::SystemEntityDefinitions::ProjectEntity
+ entity_type :minimal
+end
+```
+
+Then modify the `plugin_capabilities.yaml` file with the following content:
+
+```yaml
+---
+:plugin_module: null
+:processors: null
+:build: null
+:dsl: null
+:entity_definitions:
+ - minimal_entity.rb
+:templates: null
+```
+
+_Et voilà_, we have a plugin just providing new entity type, and it is fully working. We can create a new entity of this type:
+
+```
+$ power_stencil create minimal/test
+Created 'minimal/test'
+
+$ power_stencil get minimal/test
+---
+MinimalPlugin::Minimal:
+ :type: :minimal
+ :fields:
+ :name: test
+```
+
+All of this to demonstrate that a plugin can be almost anything, even something very minimalistic, but nevertheless you should keep on using the `power_stencil plugin --create` command and benefit from the structure it brings, as well as the possibility to become a stand-alone plugin gem...
+
+
+# Conclusion
+
+The documentation for plugins is not fully complete, so you are encouraged to read the code. Some official plugins are under development, and the documentation will be improved along their development...
+
+**:warning: As opposed to the rest of `PowerStencil`, the functionnality is nevertheless not completely frozen. This will be the case once `PowerStencil` turns 1.0.0.** Yet now _local_ plugins are almost in their final stage. Gem plugins will soon be released and then `PowerStencil` will turn 1.0.0.
+
+
[:back:][Documentation root]
<!-- End of Document -->
<!-- Pages -->
[Documentation root]: ../README.md "Back to documentation root"
[entities]: entities.md "Entities in PowerStencil"
[builds]: builds.md "Builds in PowerStencil"
[templates]: templates.md "Templates in PowerStencil"
+[post-process]: builds.md#post-process-actions "post-process actions in builds"
-
<!-- Code links -->
<!-- Illustrations -->
-
+[simple-flow-image]: images/power-stencil-simple-flow.svg
<!-- External links -->
\ No newline at end of file