This is a brief guide explaining what needs to be done to add support to Halyard for an additional cloud provider.
Please read the README.md first to get a sense for the terminology & functionality you'll be implementing.
NOTE: this is missing rosco support, so configuring custom images isn't possible yet.
NOTE: this project heavily uses lombok to generate getters & setters using the class-level
@Data
annotation. This is very helpful since a lot of the classes you'll be defining are loaded & serialized as YAML, which requires getters & setters for each field to be serialized & deserialized respectively.
The account class will be read directly from the halconfig and written
(currently) without transformation to clouddriver.yml
, so unless there is a
good reason, it's in the interest of simplicity to follow the format defined in
Clouddriver for your account class.
Here are examples:
-
Account
: The class needs to extendAccount
. Any fields that have options that can be determined at runtime, (e.g.context
) can provide a class-method with signatureprotected List<String> {%fieldName%}Options(ConfigProblemSetBuilder builder)
(e.g.protected List<String> contextOptions(ConfigProblemSetBuilder builder)
) that returns a list of human-readable options for the field. Any fields that refer to files on host-machine's filesystem need to be annotated with@LocalFile
. -
Provider
: The class needs to extendProvider<T extends Account>
whereT
is yourAccount
class. The code in this class is boilerplate.
This step is likely the largest/most time-consuming.
The validator will be run on any of your provider's accounts when necessary
(updates, additions, dependent changes, etc...), and should catch common
user mistakes and report them as Problem
s.
Each problem requires:
- A
severity
(read the comments at leach level for an understanding of when a certain level applies). - A human-readable
message
describing what the problem is.
Each problem can optionally provide:
- A human-readable
remediation
describing how to fix this problem.
There are also options
& location
fields that will be set by the validator.
To ensure that the validation matches what Clouddriver requires, please import your provider's Clouddriver submodule. An example of importing this submodule can be seen here.
Here is an example:
Validator
: This needs to extendsValidator<T extends Node>
whereT
is the type of the class you want to validate.
Here is an example:
Command
: This needs to extendAbstractNamedProviderCommand
. We'll register the sample subcommands for your provider later.
Now once this command is
registered
you'll have all the generic subcommands at your disposal (get-account
,
delete-account
, list-accounts
, enable
, and disable
) for your provider.
At this point it's valuable to point out that the command-line parameters are being parsed with JCommander. Any sort of flag manipulation you want to do will need to go through this library.
The most work here goes into creating valuable descriptions for each flag.
There is no need to do any validation here (aside from setting required=true
for parameters that can't be omitted), since everything is handled daemon-side.
Here are examples:
-
AddAccount
: Nothing fancy here. -
EditAccount
: This needs to extendAbstractEditAccountCommand<T extends Account>
whereT
is your provider's account type. TheisSet
andupdateStringList
utility methods shown in the example will come in handy here.
Finally, register these subcommands with your provider's command as shown in step 3.
In order to have your settings be picked up in settings.js, you must make two changes.
First, set up hal to inject parameters into settings.js.
bindings.put("kubernetes.default.account", kubernetesProvider.getPrimaryAccount());
bindings.put("kubernetes.default.namespace", "default");
bindings.put("kubernetes.default.proxy", "localhost:8001");
Then, update the settings.js
that halyard grabs so that it can support injection of the variables you've defined for your provider.
The key defined above is replaced with the value given.
var kubernetes = {
defaults: {
account: '{%kubernetes.default.account%}',
namespace: '{%kubernetes.default.namespace%}',
proxy: '{%kubernetes.default.proxy%}'
}
};
Also make sure to set providers.yourProvider
in the same file
to equal the variable for your provider.
providers: {
...
kubernetes: kubernetes,
},