power_stencil 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +194 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/update_plugin_template +79 -0
- data/doc/builds.md +267 -0
- data/doc/entities.md +964 -0
- data/doc/example_use_cases.md +59 -0
- data/doc/images/power-stencil-architecture.svg +151 -0
- data/doc/images/power-stencil-entity-build.svg +481 -0
- data/doc/images/power-stencil-entity-creation.svg +375 -0
- data/doc/images/power-stencil-project-overview.svg +2534 -0
- data/doc/images/power-stencil-simple-flow.svg +265 -0
- data/doc/plugins.md +169 -0
- data/doc/templates.md +332 -0
- data/etc/base_commands_definition.yml +259 -0
- data/etc/meta_templates/plugin_seed/etc/command_line.yaml +12 -0
- data/etc/meta_templates/plugin_seed/etc/plugin_config.yaml +4 -0
- data/etc/meta_templates/plugin_seed/etc/templates/.git_keep +0 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}.rb.erb +34 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/entity_definitions/{entity}_entity.rb.erb +11 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/plugin_helper.rb.erb +17 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/version.rb.erb +3 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/{entity}_processor.rb.erb +19 -0
- data/etc/meta_templates/plugin_seed/psplugin_{entity}.gemspec +36 -0
- data/etc/power_stencil.yaml +92 -0
- data/etc/templates/plugin_definition/.gitignore +11 -0
- data/etc/templates/plugin_definition/.rspec +3 -0
- data/etc/templates/plugin_definition/.travis.yml +5 -0
- data/etc/templates/plugin_definition/CODE_OF_CONDUCT.md +74 -0
- data/etc/templates/plugin_definition/Gemfile +6 -0
- data/etc/templates/plugin_definition/LICENSE.txt +21 -0
- data/etc/templates/plugin_definition/README.md +43 -0
- data/etc/templates/plugin_definition/Rakefile +6 -0
- data/etc/templates/plugin_definition/bin/console +14 -0
- data/etc/templates/plugin_definition/bin/setup +8 -0
- data/etc/templates/plugin_definition/etc/command_line.yaml +12 -0
- data/etc/templates/plugin_definition/etc/plugin_config.yaml +4 -0
- data/etc/templates/plugin_definition/etc/templates/.git_keep +1 -0
- data/etc/templates/plugin_definition/lib/{entity}.rb.erb +34 -0
- data/etc/templates/plugin_definition/lib/{entity}/entity_definitions/{entity}_entity.rb.erb +11 -0
- data/etc/templates/plugin_definition/lib/{entity}/plugin_helper.rb.erb +17 -0
- data/etc/templates/plugin_definition/lib/{entity}/version.rb.erb +3 -0
- data/etc/templates/plugin_definition/lib/{entity}/{entity}_processor.rb.erb +19 -0
- data/etc/templates/plugin_definition/psplugin_{entity}.gemspec +36 -0
- data/etc/templates/plugin_definition/spec/spec_helper.rb +14 -0
- data/etc/templates/plugin_definition/spec/{entity}_spec.rb +9 -0
- data/etc/templates/project/.copy_ignore +2 -0
- data/etc/templates/project/.gitignore.erb +6 -0
- data/etc/templates/project/.ps_project/entities/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/entities/README.md +11 -0
- data/etc/templates/project/.ps_project/entity_definitions/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/entity_definitions/README.md +15 -0
- data/etc/templates/project/.ps_project/personal-config.yaml +8 -0
- data/etc/templates/project/.ps_project/plugins/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/templates-templates/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/templates-templates/README.md +13 -0
- data/etc/templates/project/.ps_project/user_entities/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/user_entities/README.md +12 -0
- data/etc/templates/project/.ps_project/versioned-config.yaml +6 -0
- data/etc/templates/simple_exec/main.sh +4 -0
- data/exe/power_stencil +28 -0
- data/lib/power_stencil.rb +53 -0
- data/lib/power_stencil/command_processors/build.rb +43 -0
- data/lib/power_stencil/command_processors/check.rb +35 -0
- data/lib/power_stencil/command_processors/create.rb +70 -0
- data/lib/power_stencil/command_processors/delete.rb +38 -0
- data/lib/power_stencil/command_processors/edit.rb +35 -0
- data/lib/power_stencil/command_processors/entity_helper.rb +105 -0
- data/lib/power_stencil/command_processors/get.rb +22 -0
- data/lib/power_stencil/command_processors/info.rb +41 -0
- data/lib/power_stencil/command_processors/init.rb +47 -0
- data/lib/power_stencil/command_processors/new_plugin.rb +31 -0
- data/lib/power_stencil/command_processors/root.rb +27 -0
- data/lib/power_stencil/command_processors/shell.rb +37 -0
- data/lib/power_stencil/command_processors/trace_helper.rb +20 -0
- data/lib/power_stencil/dsl/base.rb +24 -0
- data/lib/power_stencil/dsl/entities.rb +46 -0
- data/lib/power_stencil/dsl/plugin_generation.rb +17 -0
- data/lib/power_stencil/engine/base.rb +50 -0
- data/lib/power_stencil/engine/build_handling.rb +77 -0
- data/lib/power_stencil/engine/directory_processor.rb +111 -0
- data/lib/power_stencil/engine/entities_definitions.rb +42 -0
- data/lib/power_stencil/engine/entities_handling.rb +76 -0
- data/lib/power_stencil/engine/entity_engine.rb +20 -0
- data/lib/power_stencil/engine/init_engine.rb +18 -0
- data/lib/power_stencil/engine/project_engine.rb +75 -0
- data/lib/power_stencil/engine/renderers/erb.rb +21 -0
- data/lib/power_stencil/error.rb +20 -0
- data/lib/power_stencil/initializer.rb +87 -0
- data/lib/power_stencil/plugins/base.rb +54 -0
- data/lib/power_stencil/plugins/capabilities.rb +30 -0
- data/lib/power_stencil/plugins/command_line.rb +27 -0
- data/lib/power_stencil/plugins/config.rb +32 -0
- data/lib/power_stencil/plugins/dependencies.rb +32 -0
- data/lib/power_stencil/plugins/gem.rb +57 -0
- data/lib/power_stencil/plugins/require.rb +77 -0
- data/lib/power_stencil/plugins/templates.rb +21 -0
- data/lib/power_stencil/project/base.rb +79 -0
- data/lib/power_stencil/project/config.rb +54 -0
- data/lib/power_stencil/project/create.rb +30 -0
- data/lib/power_stencil/project/info.rb +72 -0
- data/lib/power_stencil/project/paths.rb +119 -0
- data/lib/power_stencil/project/plugins.rb +89 -0
- data/lib/power_stencil/project/proxy.rb +13 -0
- data/lib/power_stencil/project/templates.rb +56 -0
- data/lib/power_stencil/project/versioning.rb +29 -0
- data/lib/power_stencil/system_entity_definitions/all.rb +14 -0
- data/lib/power_stencil/system_entity_definitions/buildable.rb +23 -0
- data/lib/power_stencil/system_entity_definitions/entity_override.rb +8 -0
- data/lib/power_stencil/system_entity_definitions/entity_project_common.rb +33 -0
- data/lib/power_stencil/system_entity_definitions/has_associated_files.rb +13 -0
- data/lib/power_stencil/system_entity_definitions/non_persistent.rb +14 -0
- data/lib/power_stencil/system_entity_definitions/plugin.rb +17 -0
- data/lib/power_stencil/system_entity_definitions/process_descriptor.rb +15 -0
- data/lib/power_stencil/system_entity_definitions/project_config.rb +24 -0
- data/lib/power_stencil/system_entity_definitions/project_entity.rb +16 -0
- data/lib/power_stencil/system_entity_definitions/simple_exec.rb +47 -0
- data/lib/power_stencil/utils/directory_processor.rb +54 -0
- data/lib/power_stencil/utils/file_edit.rb +87 -0
- data/lib/power_stencil/utils/file_helper.rb +56 -0
- data/lib/power_stencil/utils/gem_utils.rb +13 -0
- data/lib/power_stencil/utils/secure_require.rb +26 -0
- data/lib/power_stencil/utils/semantic_version.rb +128 -0
- data/lib/power_stencil/version.rb +3 -0
- data/power_stencil.gemspec +32 -0
- metadata +287 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -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
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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"
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -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__)
|
data/bin/setup
ADDED
@@ -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
|
+
|
data/doc/builds.md
ADDED
@@ -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 !"
|