I want to try new rule based configuration in Gradle to configure my plugin. Plugin's purspose is uploading data to cloud storages, like Google Drive or S3. I need a configuration for each storage the user want's to use. So, what I want to achieve is:
model {
backup { // this is a container for all storages I want to support
googleDrive {
clientId = ''
clientSecret = ''
accessToken = ''
refreshToken = ''
}
s3 {
// S3 specific config (like API keys)
}
}
}
In my plugin I configure rule source for backup
element:
class BackupPlugin implements Plugin<Project> {
static class Rules extends RuleSource {
@Model
void backup(BackupPluginExtension backupModel) {}
}
}
@Managed
interface BackupPluginExtension {
GoogleDrive getGoogleDrive()
void setGoogleDrive(GoogleDrive googleDrive)
}
@Managed
interface GoogleDrive {
String getClientId()
void setClientId(String clientId)
String getClientSecret()
void setClientSecret(String clientSecret)
String getAccessToken()
void setAccessToken(String accessToken)
String getRefreshToken()
void setRefreshToken(String refreshToken)
}
But, that doesn't work saying: Could not find method googleDrive() for arguments [build_8w85xu7hrz3atgeg839d33hzl$_run_closure1_closure2_closure3@1b06ac95] on root project 'test'.
. Looks like it tries to call methods inside backup
and not configure nested beans.
So, what is the correct syntax for that?
I know about named collections, but the question is how to configure custom bean hierarchies.
After playing with it for a while, it seems that making googleDrive
read-only (i.e. by removing setGoogleDrive()
setter) fixes your problem (I get BUILD SUCCESSFUL when running gradle model
).
And after few minor modifications (using @Mutate
instead of Plugin.apply
), it looks like this:
apply plugin: BackupPlugin
class BackupPlugin extends RuleSource {
@Model
void backup(BackupPluginExtension backupModel) {
}
@Mutate void createTasks(ModelMap<Task> tasks, BackupPluginExtension model) {
tasks.create("backup") {
doLast {
// ... do stuff
println "googleDrive.clientId = ${model.googleDrive.clientId}"
}
}
}
}
@Managed
interface BackupPluginExtension {
GoogleDrive getGoogleDrive()
// void setGoogleDrive(GoogleDrive googleDrive)
}
@Managed
interface GoogleDrive {
String getClientId()
void setClientId(String clientId)
String getClientSecret()
void setClientSecret(String clientSecret)
String getAccessToken()
void setAccessToken(String accessToken)
String getRefreshToken()
void setRefreshToken(String refreshToken)
}
model {
backup { // this is a container for all storages I want to support
googleDrive {
clientId = 'someId'
clientSecret = ''
accessToken = ''
refreshToken = ''
}
}
}
Running gradle backup
on this prints googleDrive.clientId = someId
.
Here is a model example of bean hierarchy collection inspired from Gradle package samples/modelRules/ruleSourcePluginEach/
.
BackupStorage
contains common attributes for both GoogleDrive
and S3
storages.
apply plugin: BackupPlugin
model {
backup {
storage1(GoogleDrive) {
clientId = '1'
clientSecret = ''
accessToken = ''
refreshToken = ''
}
storage2(S3) {
clientId = '2'
}
storage3(GoogleDrive) {
clientId = '3'
clientSecret = ''
accessToken = ''
refreshToken = ''
}
}
}
class BackupPlugin implements Plugin<Project> {
void apply(Project p) { }
static class Rules extends RuleSource {
@Model void backup(ModelMap<BackupStorage> bs) {
}
}
}
@Managed
interface BackupStorage {
String getClientId()
void setClientId(String clientId)
}
@Managed
interface GoogleDrive extends BackupStorage {
String getClientSecret()
void setClientSecret(String clientSecret)
String getAccessToken()
void setAccessToken(String accessToken)
String getRefreshToken()
void setRefreshToken(String refreshToken)
}
@Managed
interface S3 extends BackupStorage {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With