-
Notifications
You must be signed in to change notification settings - Fork 53
Creator: Generators and Capabilities in depth
Both the Generator and the Capability interface have a single apply()
function:
fun apply(resources: Resources, props: Properties, extra: Properties): Resources
It's arguments and their usage:
- resources - An object of type Resources that makes it really easy to deal with K8s/OpenShift resources.
- props - Properties, a freely usable HashMap containing the properties that can be used to tell the Generator/Capability to change its behavior. It's very recommended to not have any required properties. Make sure to create usable defaults in all cases.
- extra - Properties, a freely usable HashMap the Generator/Capability can use to pass information it considers useful back up the chain. These properties can be used to convey information that can't be obtained, extracted, deduced somehow from the input properties (props).
The method returns the original resources with the Generator/Capability's changes applied (it's not necessary to create a new object, changes can be applied directly to the original)
To make life easier for the Generator/Capability developer it's really recommended that instead of implementing the Generator
or Capability
interface, as mentioned earlier, the Generator or Capability extends BaseGenerator or BaseCapability respectively instead. The reason for this is that it adds a set of utility methods that make it easy to perform the most common tasks (somewhat simplified):
val sourceDir: Path
val targetDir: Path
fun generator(generatorConstructor): Generator
fun name(vararg parts: Any?): String
fun copy(from: Path, to: Path?)
fun copyVersioned(runtime: Runtime?, to: Path?)
fun filesCopied(from: Path, to: Path?): Boolean
fun filesCopiedVersioned(runtime: Runtime?, to: Path?): Boolean
fun move(original: Path, to: Path)
fun transform(pattern: String, transformer: Transformer, dir: Path)
fun transform(patterns: List<String>, transformer: Transformer, dir: Path)
fun appendFile(targetFile: Path, sourceFile: Path)
fun updatePom(appName: String, groupId: String, artifactId: String, version: String, pomFile: Path)
fun mergePoms(sourcePom: Path, targetPom: Path)
fun mergeVersionedPoms(runtime: Runtime?, targetPom: Path)
fun mergePackageJson(source: Path, target: Path)
fun mergeVersionedPackageJson(runtime: Runtime?, target: Path)
fun addResources(resources: Resources, transformer: Transformer, from: Path)
fun addVersionedResources(resources: Resources, transformer: Transformer, runtime: Runtime?)
- sourceDir - The path the the Generator/Capability's resource folder
- targetDir - The path to the generated project's target folder
-
generator - The function to call when you want to apply another Generator as part of this Generator/Capability's work. The
generatorConstructor
is the reference to the Generator class itself, its "constructor", that you want to apply. You'll get back an instance of that Generator after which you can call itsapply()
method. (eg.await generator(SuperDuper).apply(resources, props, extra)
- name - Just returns all its string arguments joined with hypens
-
copy - Copies all files from the given source file/folder to the destination file/folder. By default it will assume the source is the
files
sub folder from the Generator/Capability's own resource folder (ie.sourceDir
) and theto
is the generated project's target folder (ie.targetDir
). -
filesCopied - Returns a boolean indicating if all the indicated files have been copied. It uses the same defaults as
copy()
. This can be used to detect if all the files were copied during a previous execution of this or another Generator/Capability. -
move - Moves/renames a single file. Both the
from
andto
arguments are expected to be relative to the project's target folder (ie.targetDir
). -
transform - Transforms the indicated files using the given transformer. The
pattern
can be a file path with a glob pattern, eg.src/**/*.java
. It can even be an list of patterns. All paths will be taken as being relative to the generated project's target folder (ie.targetDir
). Take a look at transformers to see which are available and how they work. -
appendFile - Appends the contents of the
sourceFile
to the end of thetargetFile
. ThesourceFile
is expected to be relative to the Generator's own resource folder (ie.sourceDir
) while thetargetFile
is expected to be relative to the project's target folder (ie.targetDir
). -
updatePom - Updates the Application Name, GroupId, ArtifactId and Version of a Maven POM file. The
pomFile
is a reference to the POM file that should be updated. This path will be relative to the generated project's target folder (ie.targetDir
). By default it will refer to thepom.xml
file in the root of the target folder. -
mergePoms - Merges the contents of the
sourcePom
into thetargetPom
. ThesourcePom
path will be relative to the Generator/Capability's own folder (ie.sourceDir
) and by default will refer tomerge/pom.xml
. If you make sure to put your POM file in that location you don't need to specify anything else. ThetargetPom
is a reference to the POM file that should be updated. This path will be relative to the generated project's target folder (ie.targetDir
). By default it will refer to thepom.xml
file in the root of the target folder. -
mergeVersionedPoms - A special version of the
mergePoms()
function that takes aruntime
as its source argument, not a file path. Instead the function will use the runtime's version to look for a file namedmerge-VERSION/pom.xml
(where VERSION is replaced with the runtime's version). -
mergePackageJson - Merges the contents of the
sourceJson
into thetargetJson
. ThesourceJson
path will be relative to the Generator/Capability's own folder (ie.sourceDir
) and by default will refer tomerge/package.json
. If you make sure to put your POM file in that location you don't need to specify anything else. ThetargetJson
is a reference to the POM file that should be updated. This path will be relative to the generated project's target folder (ie.targetDir
). By default it will refer to thepom.xml
file in the root of the target folder.
NB: Even though Capabilities have access to the same methods as Generators they really should never copy or change files by themselves, nor should they directly change the list of k8s/OpenShift resources. They should always delegate that to a Generator.
IMPORTANT: One thing to take into account when creating Generators is that they can be executed more than once on the same project. For example when you apply several Capabilities it's almost certain that all of them will apply a Runtime Generator to set up basic Runtime support. But if doing so would create duplicates or undo previously made changes then it's the responsibility of the Generator to make sure that this will not happen!
At the same time it's perfectly possible for a Generator to be applied multiple times with different properties (perhaps differently named services are created for example). So the code will need to check if Resources with the same name already exists or if files have already been copied/created and skip doing its work if true. These situations should be silently handled, no exceptions should be thrown or (log) messages written!
Capabilities can have an optional extra method that gets called at the end of the apply process. It will actually be called on all Capabilities that have been added so far to the project, now or at a previous time. This means that the post processing can take into account the full combination of applied Capabilities to act upon.
This is what the method looks like:
fun postApply(resources: Resources, props: Properties, deployment: DeploymentDescriptor): Resources
It's arguments and their usage:
- resources - An object of type Resources that makes it really easy to deal with K8s/OpenShift resources.
- props - Properties, a freely usable HashMap containing the properties that can be used to tell the Generator/Capability to change its behavior. It's very recommended to not have any required properties. Make sure to create usable defaults in all cases.
- deployment - This is the final Deployment Descriptor which is basically a record of all Capabilities that have been applied to the project so far. With this information it is possible to re-create a project from scratch.