power_stencil 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +194 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/bin/update_plugin_template +79 -0
  13. data/doc/builds.md +267 -0
  14. data/doc/entities.md +964 -0
  15. data/doc/example_use_cases.md +59 -0
  16. data/doc/images/power-stencil-architecture.svg +151 -0
  17. data/doc/images/power-stencil-entity-build.svg +481 -0
  18. data/doc/images/power-stencil-entity-creation.svg +375 -0
  19. data/doc/images/power-stencil-project-overview.svg +2534 -0
  20. data/doc/images/power-stencil-simple-flow.svg +265 -0
  21. data/doc/plugins.md +169 -0
  22. data/doc/templates.md +332 -0
  23. data/etc/base_commands_definition.yml +259 -0
  24. data/etc/meta_templates/plugin_seed/etc/command_line.yaml +12 -0
  25. data/etc/meta_templates/plugin_seed/etc/plugin_config.yaml +4 -0
  26. data/etc/meta_templates/plugin_seed/etc/templates/.git_keep +0 -0
  27. data/etc/meta_templates/plugin_seed/lib/{entity}.rb.erb +34 -0
  28. data/etc/meta_templates/plugin_seed/lib/{entity}/entity_definitions/{entity}_entity.rb.erb +11 -0
  29. data/etc/meta_templates/plugin_seed/lib/{entity}/plugin_helper.rb.erb +17 -0
  30. data/etc/meta_templates/plugin_seed/lib/{entity}/version.rb.erb +3 -0
  31. data/etc/meta_templates/plugin_seed/lib/{entity}/{entity}_processor.rb.erb +19 -0
  32. data/etc/meta_templates/plugin_seed/psplugin_{entity}.gemspec +36 -0
  33. data/etc/power_stencil.yaml +92 -0
  34. data/etc/templates/plugin_definition/.gitignore +11 -0
  35. data/etc/templates/plugin_definition/.rspec +3 -0
  36. data/etc/templates/plugin_definition/.travis.yml +5 -0
  37. data/etc/templates/plugin_definition/CODE_OF_CONDUCT.md +74 -0
  38. data/etc/templates/plugin_definition/Gemfile +6 -0
  39. data/etc/templates/plugin_definition/LICENSE.txt +21 -0
  40. data/etc/templates/plugin_definition/README.md +43 -0
  41. data/etc/templates/plugin_definition/Rakefile +6 -0
  42. data/etc/templates/plugin_definition/bin/console +14 -0
  43. data/etc/templates/plugin_definition/bin/setup +8 -0
  44. data/etc/templates/plugin_definition/etc/command_line.yaml +12 -0
  45. data/etc/templates/plugin_definition/etc/plugin_config.yaml +4 -0
  46. data/etc/templates/plugin_definition/etc/templates/.git_keep +1 -0
  47. data/etc/templates/plugin_definition/lib/{entity}.rb.erb +34 -0
  48. data/etc/templates/plugin_definition/lib/{entity}/entity_definitions/{entity}_entity.rb.erb +11 -0
  49. data/etc/templates/plugin_definition/lib/{entity}/plugin_helper.rb.erb +17 -0
  50. data/etc/templates/plugin_definition/lib/{entity}/version.rb.erb +3 -0
  51. data/etc/templates/plugin_definition/lib/{entity}/{entity}_processor.rb.erb +19 -0
  52. data/etc/templates/plugin_definition/psplugin_{entity}.gemspec +36 -0
  53. data/etc/templates/plugin_definition/spec/spec_helper.rb +14 -0
  54. data/etc/templates/plugin_definition/spec/{entity}_spec.rb +9 -0
  55. data/etc/templates/project/.copy_ignore +2 -0
  56. data/etc/templates/project/.gitignore.erb +6 -0
  57. data/etc/templates/project/.ps_project/entities/.gitkeep +0 -0
  58. data/etc/templates/project/.ps_project/entities/README.md +11 -0
  59. data/etc/templates/project/.ps_project/entity_definitions/.gitkeep +0 -0
  60. data/etc/templates/project/.ps_project/entity_definitions/README.md +15 -0
  61. data/etc/templates/project/.ps_project/personal-config.yaml +8 -0
  62. data/etc/templates/project/.ps_project/plugins/.gitkeep +0 -0
  63. data/etc/templates/project/.ps_project/templates-templates/.gitkeep +0 -0
  64. data/etc/templates/project/.ps_project/templates-templates/README.md +13 -0
  65. data/etc/templates/project/.ps_project/user_entities/.gitkeep +0 -0
  66. data/etc/templates/project/.ps_project/user_entities/README.md +12 -0
  67. data/etc/templates/project/.ps_project/versioned-config.yaml +6 -0
  68. data/etc/templates/simple_exec/main.sh +4 -0
  69. data/exe/power_stencil +28 -0
  70. data/lib/power_stencil.rb +53 -0
  71. data/lib/power_stencil/command_processors/build.rb +43 -0
  72. data/lib/power_stencil/command_processors/check.rb +35 -0
  73. data/lib/power_stencil/command_processors/create.rb +70 -0
  74. data/lib/power_stencil/command_processors/delete.rb +38 -0
  75. data/lib/power_stencil/command_processors/edit.rb +35 -0
  76. data/lib/power_stencil/command_processors/entity_helper.rb +105 -0
  77. data/lib/power_stencil/command_processors/get.rb +22 -0
  78. data/lib/power_stencil/command_processors/info.rb +41 -0
  79. data/lib/power_stencil/command_processors/init.rb +47 -0
  80. data/lib/power_stencil/command_processors/new_plugin.rb +31 -0
  81. data/lib/power_stencil/command_processors/root.rb +27 -0
  82. data/lib/power_stencil/command_processors/shell.rb +37 -0
  83. data/lib/power_stencil/command_processors/trace_helper.rb +20 -0
  84. data/lib/power_stencil/dsl/base.rb +24 -0
  85. data/lib/power_stencil/dsl/entities.rb +46 -0
  86. data/lib/power_stencil/dsl/plugin_generation.rb +17 -0
  87. data/lib/power_stencil/engine/base.rb +50 -0
  88. data/lib/power_stencil/engine/build_handling.rb +77 -0
  89. data/lib/power_stencil/engine/directory_processor.rb +111 -0
  90. data/lib/power_stencil/engine/entities_definitions.rb +42 -0
  91. data/lib/power_stencil/engine/entities_handling.rb +76 -0
  92. data/lib/power_stencil/engine/entity_engine.rb +20 -0
  93. data/lib/power_stencil/engine/init_engine.rb +18 -0
  94. data/lib/power_stencil/engine/project_engine.rb +75 -0
  95. data/lib/power_stencil/engine/renderers/erb.rb +21 -0
  96. data/lib/power_stencil/error.rb +20 -0
  97. data/lib/power_stencil/initializer.rb +87 -0
  98. data/lib/power_stencil/plugins/base.rb +54 -0
  99. data/lib/power_stencil/plugins/capabilities.rb +30 -0
  100. data/lib/power_stencil/plugins/command_line.rb +27 -0
  101. data/lib/power_stencil/plugins/config.rb +32 -0
  102. data/lib/power_stencil/plugins/dependencies.rb +32 -0
  103. data/lib/power_stencil/plugins/gem.rb +57 -0
  104. data/lib/power_stencil/plugins/require.rb +77 -0
  105. data/lib/power_stencil/plugins/templates.rb +21 -0
  106. data/lib/power_stencil/project/base.rb +79 -0
  107. data/lib/power_stencil/project/config.rb +54 -0
  108. data/lib/power_stencil/project/create.rb +30 -0
  109. data/lib/power_stencil/project/info.rb +72 -0
  110. data/lib/power_stencil/project/paths.rb +119 -0
  111. data/lib/power_stencil/project/plugins.rb +89 -0
  112. data/lib/power_stencil/project/proxy.rb +13 -0
  113. data/lib/power_stencil/project/templates.rb +56 -0
  114. data/lib/power_stencil/project/versioning.rb +29 -0
  115. data/lib/power_stencil/system_entity_definitions/all.rb +14 -0
  116. data/lib/power_stencil/system_entity_definitions/buildable.rb +23 -0
  117. data/lib/power_stencil/system_entity_definitions/entity_override.rb +8 -0
  118. data/lib/power_stencil/system_entity_definitions/entity_project_common.rb +33 -0
  119. data/lib/power_stencil/system_entity_definitions/has_associated_files.rb +13 -0
  120. data/lib/power_stencil/system_entity_definitions/non_persistent.rb +14 -0
  121. data/lib/power_stencil/system_entity_definitions/plugin.rb +17 -0
  122. data/lib/power_stencil/system_entity_definitions/process_descriptor.rb +15 -0
  123. data/lib/power_stencil/system_entity_definitions/project_config.rb +24 -0
  124. data/lib/power_stencil/system_entity_definitions/project_entity.rb +16 -0
  125. data/lib/power_stencil/system_entity_definitions/simple_exec.rb +47 -0
  126. data/lib/power_stencil/utils/directory_processor.rb +54 -0
  127. data/lib/power_stencil/utils/file_edit.rb +87 -0
  128. data/lib/power_stencil/utils/file_helper.rb +56 -0
  129. data/lib/power_stencil/utils/gem_utils.rb +13 -0
  130. data/lib/power_stencil/utils/secure_require.rb +26 -0
  131. data/lib/power_stencil/utils/semantic_version.rb +128 -0
  132. data/lib/power_stencil/version.rb +3 -0
  133. data/power_stencil.gemspec +32 -0
  134. metadata +287 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0553232c716ddf2858efa77a0d9617ca39576d15
4
+ data.tar.gz: cad65330d8a994849b940c519b008cdb9ba39990
5
+ SHA512:
6
+ metadata.gz: 84ded250b7f0080a28e8d07a3fddad16b5a5fc4c220bf87f1a0b7591d9b68804f954e70a56b0844d43f924e9b8849457bf16cd4af39eec806080905a68908151
7
+ data.tar.gz: 0be35290850eb3ada35a95a6278904a430d19d96d3fafc68ba81d3ea0018657bdd7baf95990f5abafffb69967e7244bd87965fb8323d8550446ce3e5c69e4299
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /etc/templates/plugin_definition-*.old/
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ /.idea/
13
+ /test/test_project/build/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.15.1
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at lbnetid+gh@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in power_stencil.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Laurent B.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,194 @@
1
+ PowerStencil
2
+ ============
3
+
4
+ `Power Stencil` is the Swiss-army knife templating workflow for developers and ops.
5
+
6
+ <!-- TOC -->
7
+
8
+ - [Core concepts](#core-concepts)
9
+ - [Pfff, yet another templating engine...](#pfff-yet-another-templating-engine)
10
+ - [Installation](#installation)
11
+ - [Usage](#usage)
12
+ - [Help](#help)
13
+ - [Creating a `PowerStencil` project](#creating-a-powerstencil-project)
14
+ - [`PowerStencil` project structure](#powerstencil-project-structure)
15
+ - [Getting started](#getting-started)
16
+ - [Contributing](#contributing)
17
+ - [License](#license)
18
+ - [Code of Conduct](#code-of-conduct)
19
+
20
+ <!-- /TOC -->
21
+
22
+ # Core concepts
23
+
24
+ `PowerStencil` proposes a radical approach on how to manage your shared configuration.
25
+
26
+ Internally `PowerStencil` is composed of a data repository and a pretty standard templating flow to generate whatever is needed by your project or organization:
27
+ ![simple-flow-image]
28
+ Configuration is one of the most complex things to maintain, and anyone who participated in a large scale piece of software or documentation knows how complex it is to maintain, keep consistent and avoid duplication on the long run across the various projects that may share this configuration.
29
+
30
+ `PowerStencil` provides **development and operations friendly workflows to fully manage the maintenance of a complex shared config** in order to generate anything you may want like _documentation_, _static sites_, _code_, _configuration_ for multiple tools..., while **avoiding duplication, and manage it like code** !
31
+
32
+ It is a common pattern to introduce a database to manage this configuration, and it is a very bad idea because it implies extra tooling, and specific developments that de-facto become single point of failure at the heart of your development process. Why would you do that when something as versatile and ubiquitous as Git exists that will __integrate smoothly within your existing development and operations workflows__, builds, CI/CD, while benefiting from all the goodness provided by Git, like branches, decentralization, versioning, tags, code reviews, traceability, simplified fallbacks etc... ?
33
+
34
+ **With `PowerStencil` everything is maintained in a git repository**: data, templates, specific code. No more config loss, no more change applied without a full lineage.
35
+
36
+ See some real world [example use cases].
37
+
38
+ The `PowerStencil` gem provides the `power_stencil` executable which is a pluggable CLI to:
39
+
40
+ - CRUD [entities] using either an editor or a dedicated REPL
41
+ - Manage [templates]
42
+ - Manage [builds]
43
+ - Create and manipulate [plugins]
44
+
45
+ # Pfff, yet another templating engine...
46
+
47
+ **Actually `PowerStencil` is _not_ a templating engine** per se. Instead it uses already existing and proven templating engines.
48
+ Currently it uses [ERB], which is pretty standard in [Ruby] world, but this is not hardcoded and any templating engine could be used (in parallel, meaning different templating engines can be used automatically depending on what you actually want to generate), even if only [ERB] is implemented for the time-being, `PowerStencil` is modular from ground-up and at least a second implementation for [Haml] templating engine is planned to ease generation of XML-like files, still currently you can do it with [ERB]. See the [templates] section for more information about templates in `PowerStencil`.
49
+
50
+ No, the real value of `PowerStencil` is not really in its templating capabilities even if very powerful, but in the development flow it proposes around this templating mechanism for both development and/or operations teams, in the way you organize and trace the data which is the real asset, and in the way you can easily extend it to fit the particular needs of a project or organization.
51
+
52
+ # Installation
53
+
54
+ You need a working install of the [Ruby] language (>= 2.2).
55
+
56
+ You can install the `PowerStencil` gem by issuing the usual:
57
+
58
+ $ gem install power_stencil
59
+
60
+ # Usage
61
+
62
+ ## Help
63
+
64
+ The `power_stencil` CLI provides a contextual help. You can start by:
65
+
66
+ $ power_stencil --help
67
+
68
+ That will display a basic help:
69
+
70
+ ```shell
71
+ This is power_stencil. A powerful templating engine.
72
+ -- Options ---------------------------------------------------------------------
73
+ -v, --verbose Displays extra runtime information.
74
+ -h, --help Displays this help.
75
+ --program-version, -V, --version Displays program version.
76
+ --simulate Will not perform actual actions
77
+ --debug Debug mode
78
+ --debug-on-err, --debug-on-stderr Sends debugging to SDTERR
79
+ --log-level Defines the level of logging (0 to 5)
80
+ --log-file Specifies a file to log into
81
+ --truncate-log-file Truncates the log file (appends by default)
82
+ --project-path Specifies a startup path to use instead of '.'
83
+ --auto Bypasses command-line confirmations to the user
84
+
85
+ --------------------------------------------------------------------------------
86
+ Following subcommands exist too:
87
+ For more information you can always issue sub_command_name --help...
88
+ --------------------------------------------------------------------------------
89
+ * init: Initializes a PowerStencil repository ...
90
+ * info: Generic information about the repository ...
91
+ * new-plugin: Generates the skeleton for a plugin ...
92
+ * get: Query entities from repository ...
93
+ * shell: Opens a shell to interact with entities ...
94
+ * check: Check repository entities consistency ...
95
+ * create: Creates entities in the repository ...
96
+ * edit: Edit entities from repository ...
97
+ * delete: Delete entities from repository ...
98
+ * build: Builds entities ...
99
+ ```
100
+
101
+ The program uses the standard paradigm of sub-commands (à-la-git), and each can have its own options that you can check using:
102
+
103
+ $ power_stencil <subcommand> --help
104
+
105
+ [Plugins] may bring extra subcommands and/or options, so depending on the project you are working in, the output of `--help` may differ...
106
+
107
+ ## Creating a `PowerStencil` project
108
+
109
+ To create a new project, use the `init` sub-command. It works as you would expect. If you run it in an existing directory it will create the project here but if you want you can specify the directory where you want the project to be created:
110
+
111
+ $ power_stencil init --project-path /where/you/want
112
+
113
+ The `--project-path` option can be applied to any sub-command, but à-la-git, once the project created if you are anywhere within the project tree, you don't need to specify the project path.
114
+
115
+ ## `PowerStencil` project structure
116
+
117
+ The structure of a brand new `PowerStencil` project is the following:
118
+
119
+ ```
120
+ ├── .gitignore
121
+ └── .ps_project
122
+ ├── entities
123
+ │   └── README.md
124
+ ├── entity_definitions
125
+ │   └── README.md
126
+ ├── personal-config.yaml
127
+ ├── plugins
128
+ ├── templates-templates
129
+ │   └── README.md
130
+ ├── user_entities
131
+ │   └── README.md
132
+ └── versioned-config.yaml
133
+ ```
134
+ New directories will appear once you start some [builds] or when you will define [templates].
135
+
136
+ Not all the files in this directory should be versioned, and this the reason why there is a preconfigured `.gitignore` at the root of the project.
137
+
138
+ The project has two distinct config files. Keep the official project config in the `.ps_project/versioned-config.yaml` which, as its name suggest will be versioned. But any developer who wants to temporarily override some configuration should do it in the `.ps_project/personal-config.yaml` which is not be versioned. The content defined in the latter overrides the content of the official one. This is a clean way for anyone who wants to test something to safely do it locally without the risk to pollute the central repo.
139
+
140
+ There is the same mechanism between `.ps_project/entities` and `.ps_project/user_entities`, but as opposed to the two aforementioned config files you should not edit anything directly there, but instead interact using the CLI. More information on how to manage entities [here][entities].
141
+
142
+ The `plugins` directory can optionally contain project specific plugins. Plugins are a great way to extend `PowerStencil` for the needs of a project or organization. See the [plugins] documentation.
143
+
144
+ ## Getting started
145
+
146
+ The core of the system is the `entity`, so you should start by having a look at what entities are, how they are easily managed using the `PowerStencil` CLI and shell.
147
+
148
+ :arrow_forward: [Entities]
149
+
150
+ Then it is important to understand how to use entities within `templates`. Templates are the way to generate something (doc, code, descriptors, sites, whatever...) from the data that the entities represent.
151
+
152
+ :arrow_forward: [Templates]
153
+
154
+ The mechanism that combines entities and templates is called a `build`. A build is always attached to an entity (you build something). The result of a build is a set of files. Optionally an action can be triggered after the files are generated (could be as simple as calling a script that has been generated).
155
+
156
+ :arrow_forward: [Builds]
157
+
158
+ `PowerStencil` could stop there, and you would be able to do whatever you want, but there is a whole world beyond. `Plugins` provide a way to completely extend `PowerStencil`, further control relations between entities, implement complex post-build actions, add CLI sub-commands and options. Plugins can be local to the project or coming in the form of standard Ruby Gems ! The icing on the cake...
159
+
160
+ :arrow_forward: [Plugins]
161
+
162
+ # Contributing
163
+
164
+ Bug reports and pull requests are welcome on Gitlab at https://gitlab.com/tools4devops/power_stencil. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
165
+
166
+ ## License
167
+
168
+ The gem is available as open source under the terms of the [MIT License].
169
+
170
+ ## Code of Conduct
171
+
172
+ Everyone interacting in the PowerStencil project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct].
173
+
174
+ <!-- End of Document -->
175
+
176
+ <!-- Pages -->
177
+ [templates]: doc/templates.md "Templates in PowerStencil"
178
+ [entities]: doc/entities.md "Entities in PowerStencil"
179
+ [builds]: doc/builds.md "Builds in PowerStencil"
180
+ [plugins]: doc/plugins.md "Plugins in PowerStencil"
181
+ [example use cases]: doc/example_use_cases.md "Example uses cases using PowerStencil"
182
+ [code of conduct]: CODE_OF_CONDUCT.md
183
+
184
+ <!-- Code links -->
185
+ [ERB implementation]: lib/power_stencil/engine/renderers/erb.rb "Mostly the only module you need to clone to implement another templating engine"
186
+
187
+ <!-- Illustrations -->
188
+ [simple-flow-image]: doc/images/power-stencil-simple-flow.svg
189
+
190
+ <!-- External links -->
191
+ [MIT License]: http://opensource.org/licenses/MIT "The MIT license"
192
+ [ERB]: https://ruby-doc.org/stdlib-2.6.3/libdoc/erb/rdoc/ERB.html "Quick ERB description"
193
+ [Haml]: http://haml.info/ "The templating engine for XML-like documents"
194
+ [Ruby]: https://www.ruby-lang.org "The powerful Ruby language"
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'power_stencil'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ require 'bundler/setup'
5
+ require 'tmpdir'
6
+ require 'power_stencil'
7
+
8
+ LOGGER = Logger.new STDERR
9
+
10
+ def logger
11
+ LOGGER
12
+ end
13
+
14
+ include Climatic::Proxy
15
+ include PowerStencil::Utils::FileHelper
16
+ include PowerStencil::Utils::DirectoryProcessor
17
+
18
+ POWER_STENCIL_ETC = File.expand_path File.join( '..', '..', 'etc'), __FILE__
19
+ POWER_STENCIL_TEMPLATES_PATH = File.join POWER_STENCIL_ETC, 'templates'
20
+ PLUGIN_DEFINITION_PATH = File.join POWER_STENCIL_TEMPLATES_PATH,'plugin_definition'
21
+ PLUGIN_SEED_PATH = File.join POWER_STENCIL_ETC, 'meta_templates', 'plugin_seed'
22
+ BACKUP_PATH = "%s-#{timestamp Time.now}.old" % [PLUGIN_DEFINITION_PATH]
23
+ # puts "Plugin definition path: '#{PLUGIN_DEFINITION_PATH}'", "Backup path: '#{BACKUP_PATH}'"
24
+
25
+ def generate_gem(gem_name, dir)
26
+ Dir.chdir dir do
27
+ # Let's create a new gem using bundle
28
+ res = `bundle gem #{gem_name} --no-exe`
29
+ # Remove useless files from generated gem source
30
+ logger.debug "#{res}"
31
+ gem_path = File.join dir, gem_name
32
+ substituted_path = File.join dir, 'plugin_definition'
33
+ gitdir = File.join gem_path,'.git'
34
+ libdir = File.join gem_path,'lib'
35
+ gemspecfile = File.join gem_path, "#{gem_name}.gemspec"
36
+ FileUtils.remove_entry_secure gitdir
37
+ FileUtils.remove_entry_secure libdir
38
+ FileUtils.remove_entry_secure gemspecfile
39
+ # Copy files from power_stencil seed files
40
+ FileUtils.copy_entry PLUGIN_SEED_PATH, gem_path
41
+ # Perform file names and content substitutions
42
+ process_directory source: gem_path,
43
+ destination: substituted_path do |source_file, potential_target_file|
44
+ next if File.directory? source_file
45
+ target_file = potential_target_file.gsub gem_name, '{entity}'
46
+ logger.info "Processing #{source_file} -> #{target_file}"
47
+ file_content = File.read source_file
48
+ file_content.gsub! gem_name, '<%= plugin_module_name %>'
49
+ modes = File.stat(source_file).mode
50
+ FileUtils.mkdir_p(File.dirname target_file)
51
+ File.open(target_file, 'w') do |file|
52
+ file.puts file_content
53
+ end
54
+ logger.debug "Processed #{target_file}"
55
+ end
56
+
57
+ end
58
+ end
59
+
60
+ def update_definition_template(source_dir, dest_dir)
61
+ # Backup old plugin template definition in power stencil gem
62
+ FileUtils.mv PLUGIN_DEFINITION_PATH, BACKUP_PATH
63
+ # Copy new definition into gem
64
+ FileUtils.copy_entry source_dir, dest_dir
65
+ end
66
+
67
+ fake_gem_name = 'XXXXXXXXXXXX'
68
+
69
+ Dir.mktmpdir do |tmpdir|
70
+ Dir.chdir tmpdir do
71
+ generate_gem fake_gem_name, tmpdir
72
+ generated_gem_path = File.join(tmpdir, 'plugin_definition')
73
+ update_definition_template generated_gem_path, PLUGIN_DEFINITION_PATH
74
+ puts 'bye'
75
+ end
76
+ end
77
+
78
+
79
+
@@ -0,0 +1,267 @@
1
+ Builds
2
+ ======
3
+
4
+ <!-- TOC -->
5
+
6
+ - [Overview of the build process](#overview-of-the-build-process)
7
+ - [The "_compilation_" process](#the-_compilation_-process)
8
+ - [Extending an entity](#extending-an-entity)
9
+ - [Overriding entities and build scenarii](#overriding-entities-and-build-scenarii)
10
+ - [The "_detemplatization_" process](#the-_detemplatization_-process)
11
+ - [Post-process actions](#post-process-actions)
12
+
13
+ <!-- /TOC -->
14
+ [:back:][Documentation root]
15
+
16
+
17
+ # Overview of the build process
18
+
19
+
20
+ You build a [buildable] entity by issuing `power_stencil build <entity_type>/<entity_name>`. If you try to build an entity which is not buildable, the process fail with an error message.
21
+
22
+ Let's describe a bit more in detail what this build process is:
23
+
24
+ ![entity-build-flow]
25
+
26
+ Humm :thinking:... What is this _compilation_ step that appears on this schema ??! I thought Ruby was an interpreted language...
27
+
28
+ I guess you understood this is not a "real" _compilation_ process we are discussing about here, like in the sense of compiling some Java or C code.
29
+
30
+ # The "_compilation_" process
31
+
32
+ The mechanism of the compilation is coming from the [universe_compiler] Gem, but the two following features are the ones you really need to understand.
33
+
34
+ :information_source: The compilation process can be applied to any entity, ie it doesn't need to be [buildable] (see in next paragraph how to run the compilation). But an entity needs to be [buildable] to use `power_stencil build` which corresponds actually to _compilation_ + _detemplatization_.
35
+
36
+ ## Extending an entity
37
+
38
+ We could describe this mechanism as inheritance at entity level (not entity type !), said differently this a way for an entity to _inherit_ (or _extend_ in the `PowerStencil` paradigm) the content of another entity.
39
+
40
+ Let's try this with two `base_entities`.
41
+
42
+ First let's define a root entity to inherit from:
43
+
44
+ $ power_stencil create base_entity/root_entity --edit
45
+
46
+ and set the folloging content:
47
+
48
+ ```yaml
49
+ --- !ruby/object:PowerStencil::SystemEntityDefinitions::ProjectEntity
50
+ :name: root_entity
51
+ :property_root: value in root_entity
52
+ :array_root:
53
+ - value A
54
+ - value B
55
+ :hash_root:
56
+ item1: value 1
57
+ item2: value 2
58
+ ```
59
+
60
+ Now let's create a second entity to extend this one:
61
+
62
+ $ power_stencil create base_entity/inherited_entity --edit
63
+
64
+ And define its content as:
65
+
66
+ ```yaml
67
+ --- !ruby/object:PowerStencil::SystemEntityDefinitions::ProjectEntity
68
+ :name: inherited_entity
69
+ :a_specific_property: This one only exists in inherited entity
70
+ :extends: !psref
71
+ type: :base_entity
72
+ name: root_entity
73
+ :array_root:
74
+ - value from inherited_entity
75
+ :hash_root:
76
+ item2: value2 but from inherited
77
+ item3: value3
78
+ ```
79
+
80
+ Once done, if we do a `power_stencil get base_entity/inherited_entity --raw` this exactly what will get. But `PowerStencil` gives a possibility to see how this entity will look like after the compilation process using the `--compiled` option:
81
+
82
+ So if you do
83
+
84
+ $ power_stencil get base_entity/inherited_entity --raw --compiled
85
+
86
+ This is what you get:
87
+
88
+ ```yaml
89
+ --- !ruby/object:PowerStencil::SystemEntityDefinitions::ProjectEntity
90
+ :name: inherited_entity
91
+ :a_specific_property: This one only exists in inherited entity
92
+ :property_root: value in root_entity
93
+ :array_root:
94
+ - value from inherited_entity
95
+ :hash_root:
96
+ item1: value 1
97
+ item2: value2 but from inherited
98
+ item3: value3
99
+ :extends: !psref
100
+ type: :base_entity
101
+ name: root_entity
102
+ ```
103
+
104
+ You can notice that this second object looks now like a merged entity. Here are the rules of the merge:
105
+
106
+ - the entity extending another one has always precedence, meaning that if a property is defined in both, only the latter is kept.
107
+ - hashes are treated a bit differently as a real merge of the two hashes is performed (which is not the case of arrays or simple properties).
108
+ - the `extends` property is kept even after compilation for reference (meaning that in a template you can still access values of the entity you are extending).
109
+
110
+ :warning: **The entity you extend has to be of the same entity type** or the compilation will fail (actually unless you created the entity yaml file manually, the framework won't even let you save it if the entity inheritance is invalid) !
111
+
112
+ ## Overriding entities and build scenarii
113
+
114
+ You may have noticed from the output of `power_stencil info` that there is a type of entity named `entity_override`.
115
+
116
+ This is a very specific type of entity linked to the compilation process.
117
+
118
+ The goal of this specific entity is to provide a mechanism to override some of the properties of other entities in the scope of a _build scenario_. This is really a feature turned towards testing possibilities, by it for developers or ops, and as such generally `entity_override` are often created as [local entities] (although they really could be created as standard versioned entities).
119
+
120
+ Let's create our first override:
121
+
122
+ $ power_stencil create entity_override/test_override --edit --user-storage
123
+
124
+ And define its content:
125
+
126
+ ```yaml
127
+ --- !ruby/object:UniverseCompiler::Entity::Override
128
+ :overrides:
129
+ - !psref
130
+ type: :base_entity
131
+ name: inherited_entity
132
+ :name: test_override
133
+ :property_from_overide: foo
134
+ :scenario: dev_tests
135
+ :hash_root:
136
+ item3: overridden value
137
+ ```
138
+ :information_source: First thing to notice is that an `entity_override` is **able to override properties of multiples entities at once** ! Hence the fact the `overrides` property is an array.
139
+
140
+ :information_source: **There is no constraint on the entity types this override applies to** (as opposed to the extend mechanism)
141
+
142
+ The `scenario` property specifies the build scenario this override will be applied for.
143
+
144
+ :information_source: You can define as many `entity_overrides` as you want for a specific build scenario.
145
+
146
+ Ok, then what happens to `base_entity/inherited_entity` ?
147
+
148
+ As expected, without specifying a build scenario nothing changes
149
+
150
+ $ power_stencil get base_entity/inherited_entity --raw --compiled
151
+
152
+ ```yaml
153
+ --- !ruby/object:PowerStencil::SystemEntityDefinitions::ProjectEntity
154
+ :name: inherited_entity
155
+ :property_root: value in root_entity
156
+ :array_root:
157
+ - value from inherited_entity
158
+ :hash_root:
159
+ item1: value 1
160
+ item2: value2 but from inherited
161
+ item3: value3
162
+ :a_specific_property: This one only exists in inherited entity
163
+ :extends: !psref
164
+ type: :base_entity
165
+ name: root_entity
166
+ ```
167
+ But if you specify the dev_tests scenario:
168
+
169
+ $ power_stencil get base_entity/inherited_entity --raw --compiled --scenario dev_tests
170
+ ```yaml
171
+ --- !ruby/object:PowerStencil::SystemEntityDefinitions::ProjectEntity
172
+ :name: inherited_entity
173
+ :property_root: value in root_entity
174
+ :array_root:
175
+ - value from inherited_entity
176
+ :hash_root:
177
+ item1: value 1
178
+ item2: value2 but from inherited
179
+ item3: overridden value
180
+ :a_specific_property: This one only exists in inherited entity
181
+ :extends: !psref
182
+ type: :base_entity
183
+ name: root_entity
184
+ :property_from_overide: foo
185
+ ```
186
+
187
+ :information_source: You can notice that **the override mechanism occurs after the extend mechanism**, and both can be used on the same entities.
188
+
189
+ :information_source: The `--scenario` command line option obviously exists as well for the `build` sub-command so that you can run a build in the context of a scenario.
190
+
191
+ This override mechanism is really a great way for developers or ops to test something while being sure to avoid introducing errors in the entities repository (by "temporarily patching" an entity to perform a test... and then committing it by mistake... smells like real life, doesn't it ?).
192
+
193
+
194
+ # The "_detemplatization_" process
195
+
196
+ Now we have almost everything we need:
197
+
198
+ - We have a nice traceable mechanism to manage [entities] (our shared data), including [special features to keep them dry](#extending-an-entity) and perform [test scenarii](#overriding-entities-and-build-scenarii).
199
+ - We have a pluggable [templating mechanism][templates], with mechanisms to decide to [which files it may be applied to](#xxx_ignore-files) (or actually which files it should _not_ apply to).
200
+
201
+
202
+ When we are using `power_stencil build`, the entities are first compiled then templates associated to the entity specified are used in order to generate the "_detemplatized_" files.
203
+
204
+ Those generated files are located in a subfolder of the `build` directory of the project (which by default is not versioned as per `.git_ignore` located at the root folder of the project).
205
+
206
+ The pattern for the name of the folder where the files are generated is the following:
207
+
208
+ `build/<date_and_time_stamp><entity_type>_<entity_name>/<entity_type>_<entity_name>`
209
+
210
+ Why is there 2 times entity type and name ?
211
+
212
+ This is because `power_stencil build` accepts more than one entity as parameter and in this case the first level would be the type and name of all the entities concatenated and then there would be second level folders, one per per entity.
213
+
214
+ # Post-process actions
215
+
216
+
217
+ By default `PowerStencil` proposes the `simple_exec` entity type which provides the possibility to run any executable after the build completed. By default it will run a script `main.sh` (automatically generated), but this is completely customizable.
218
+
219
+ When you create a `simple_exec` entity:
220
+
221
+ $ power_stencil create simple_exec/example
222
+
223
+ Actually two entities are created under the hood:
224
+
225
+ ```shell
226
+ $ power_stencil get example --regexp
227
+ ---
228
+ PowerStencil::SystemEntityDefinitions::SimpleExec:
229
+ :type: :simple_exec
230
+ :fields:
231
+ :name: example
232
+ :post_process: !psref
233
+ type: :process_descriptor
234
+ name: simple_exec_example.process
235
+
236
+ ---
237
+ PowerStencil::SystemEntityDefinitions::ProcessDescriptor:
238
+ :type: :process_descriptor
239
+ :fields:
240
+ :name: simple_exec_example.process
241
+ :process: "./main.sh"
242
+
243
+ ```
244
+ It creates a `process_descriptor` entity (which is referenced from the `simple_exec` entity as the `post_process` field). So you can edit this process descriptor and define there whatever executable you want to be called.
245
+
246
+ This should already cover 95% of everything needed.
247
+
248
+ If you want to do something more custom after the build process completed, this is where you will have to do a [plugin][plugins].
249
+
250
+ [:back:][Documentation root]
251
+ <!-- End of Document -->
252
+
253
+ <!-- Pages -->
254
+ [Documentation root]: ../README.md "Back to documentation root"
255
+ [entities]: entities.md "Entities in PowerStencil"
256
+ [templates]: templates.md "Templates in PowerStencil"
257
+ [plugins]: plugins.md "Plugins in PowerStencil"
258
+ [buildable]: entities.md#buildable--buildable_by "How to make an entity buildable ?"
259
+ [local entities]: entities.md#local-unversioned-entities "Local unversioned entities"
260
+
261
+ <!-- Code links -->
262
+
263
+ <!-- Illustrations -->
264
+ [entity-build-flow]: images/power-stencil-entity-build.svg
265
+
266
+ <!-- External links -->
267
+ [universe_compiler]: https://gitlab.com/tools4devops/universe_compiler "The underlying engine to manage entities and compilation !"