2013-07-13 21 views
15

Tôi đang làm việc trên một plugin gradle (tôi không biết groovy, và chỉ bắt đầu sử dụng gradle) tích hợp với Asgard (từ netflix). Tôi muốn đối tượng mở rộng của tôi trông như thế này cho người sử dụng:Viết plugin gradle với các đối tượng mở rộng lồng nhau

asgard { 
    url = "http://asgard" 
    regions { 
    "us-east-1" { 
     autoScaling { 
     { 
      devPhase = "test" 
      min = 3 
      max = 6 
      availabilityZones = ["us-east-1a", "us-east-1b", "us-east-1c"] 
      ami = "Base AMI 2013-07-11" 
      instanceType = "m3.xlarge" 
      securityGroups = ["base", "test-application"] 
     } 
     } 
    } 
    } 
} 

Hoặc một cái gì đó gần đó. Tôi đã có thể nhận được gần với điều này bằng cách làm autoScaling một danh sách, nhưng khi bao giờ tôi cố gắng để có được một tài sản từ lớp đó có vẻ như để trở về một tài sản năng động và không bao giờ giá trị. Đây là khởi Plugin dưới đây:

import org.gradle.internal.reflect.Instantiator 

class AsgardPlugin implements Plugin<Project> { 
    void apply(Project project) { 
    project.extensions.create("asgard", AsgardPluginExtension, project) 
    project.asgard.extensions.regions = project.container(AsgardRegion) {String name -> 
     AsgardRegion region = project.gradle.services.get(Instantiator).newInstance(AsgardRegion, name) 
     assert region instanceof ExtensionAware 

     region.extensions.add("autoScaling", project.container(AsgardAutoScaling)) 

     return region 
    } 


    project.task('displayConfigs') << { 
     if(project.asgard.applicationName == null) project.asgard.applicationName = project.name 
     println "Asgard URL $project.asgard.url" 
     println "Application name $project.asgard.applicationName" 
     println "Runs on regions..." 
     project.asgard.regions.each() {region -> 
     println "\tRegion $region.name" 
     println "\tAutoScaling groups..." 
     region.autoScaling.each() {asg -> 
      println "\t\tdevPhase $asg" 
      println "\t\tdevPhase $asg.devPhase" 
      println "\t\tdevPhase $asg.get('devPhase')" 
     } 
     } 
    } 
    } 
} 

class AsgardPluginExtension { 
    String url = "http://asgard.sisa.samsung.com" 
    String applicationName 

    AsgardPluginExtension(Project project) { 
    applicationName = project.name 
    } 
} 

class AsgardRegion { 
    def String name 
    List<AsgardAutoScaling> autoScaling 
    AsgardRegion(String name) { this.name = name } 
} 

class AsgardAutoScaling { 
    String devPhase 
    int min 
    int max 
    List<String> availabilityZones 
    String ami 
    String instanceType 
    String sshKey 
    List<String> securityGroups 
} 

Khi tôi chạy nhiệm vụ, đây là những gì tôi nhìn thấy trong các bản ghi:

$ ./gradlew displayConfigs 
:displayConfigs 
Asgard URL http://asgard 
Application name gradle-asgard-plugin 
Runs on regions... 
     Region us-east-1 
     AutoScaling groups... 
Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed in Gradle 2.0. Please read http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html for information on the replacement for dynamic properties. 
Deprecated dynamic property: "devPhase" on "[email protected]", value: "test". 
Deprecated dynamic property: "min" on "[email protected]", value: "3". 
Deprecated dynamic property: "max" on "[email protected]", value: "6". 
Deprecated dynamic property: "availabilityZones" on "[email protected]", value: "[us-east-1a, us-east-1...". 
Deprecated dynamic property: "ami" on "[email protected]", value: "Base AMI 2013-07-11". 
Deprecated dynamic property: "instanceType" on "[email protected]", value: "m3.xlarge". 
Deprecated dynamic property: "securityGroups" on "[email protected]", value: "[base, test-application]". 
       devPhase 
       devPhase test 
       devPhase [email protected]('devPhase') 

BUILD SUCCESSFUL 

Total time: 1.996 secs 

Tôi đi về việc này hoàn toàn sai? Nếu không làm thế nào tôi có thể nhận được giá trị từ tài sản động (cố gắng có được và giá trị, nhưng những người dường như không làm việc).

Cảm ơn bạn đã đọc thời gian này.

EDIT dựa off @ peter-niederwieser phản hồi

Cảm ơn peter-niederwieser cho gợi ý của bạn. Sau khi lấy lời khuyên của bạn và nhìn vào cách đóng cửa làm việc tôi nghĩ rằng tôi có một sự hiểu biết tốt hơn về làm thế nào để đặt ra để làm những gì tôi muốn thử.

Đây là cú pháp của các plugin bây giờ:

asgard { 
    url = "http://asgard" 
    regions { 
    "us-east-1" { 
     autoScaling { 
      devPhase = "test" 
      min = 3 
      max = 6 
      availabilityZones = ["a", "b", "c"] 
      ami = "Base AMI 2013-07-11" 
      instanceType = "m3.xlarge" 
      securityGroups = ["base", "test-application"] 
     } 
     autoScaling { 
     devPhase = "stage" 
     } 
    } 

    "us-west-1" { 
     autoScaling { 
     devPhase = "test" 
     } 
     autoScaling { 
     devPhase = "stage" 
     } 
    } 

    } 
} 

Mã để hỗ trợ này có thể được tìm thấy ở đây:

import org.gradle.internal.reflect.Instantiator 

class AsgardPlugin implements Plugin<Project> { 
    void apply(Project project) { 
    project.extensions.create("asgard", AsgardPluginExtension, project) 
    project.asgard.extensions.regions = project.container(AsgardRegion) {String name -> 
     AsgardRegion region = project.gradle.services.get(Instantiator).newInstance(AsgardRegion, name, project) 
     assert region instanceof ExtensionAware 

     return region 
    } 


    project.task('displayConfigs') << { 
     if(project.asgard.applicationName == null) project.asgard.applicationName = project.name 
     println "Asgard URL $project.asgard.url" 
     println "Application name $project.asgard.applicationName" 
     println "Runs on regions..." 
     project.asgard.regions.each() {region -> 
     println "\tRegion $region.name" 
     println "\tAutoScaling groups..." 
     region.autoScaling.each() {asg -> 
      println "\t\tdevPhase $asg.devPhase" 
     } 
     } 
    } 
    } 
} 

class AsgardPluginExtension { 
    String urlgg 
    String applicationName 

    AsgardPluginExtension(Project project) { 
    applicationName = project.name 
    } 
} 

class AsgardRegion { 
    String name 
    Project project 
    List<AsgardAutoScaling> autoScaling = [] 

    AsgardRegion(String name, Project project) { 
    this.name = name 
    this.project = project 
    } 

    void autoScaling(Closure closure) { 
    def asg = new AsgardAutoScaling() 
    project.configure(asg, closure) 
    autoScaling.add(asg) 
    } 
} 

class AsgardAutoScaling { 
    String devPhase 
    int min 
    int max 
    List<String> availabilityZones 
    String ami 
    String instanceType 
    String sshKey 
    List<String> securityGroups 
} 

Đây là kết quả tôi thấy khi chạy:

$ ./gradlew displayConfigs 
:displayConfigs 
Asgard URL http://asgard 
Application name gradle-asgard-plugin 
Runs on regions... 
     Region us-east-1 
     AutoScaling groups... 
       devPhase test 
       devPhase stage 
     Region us-west-1 
     AutoScaling groups... 
       devPhase test 
       devPhase stage 

BUILD SUCCESSFUL 

Total time: 1.929 secs 

Trả lời

6

Một số gợi ý:

  • Không cần thêm tiện ích mở rộng autoScaling vào region vì lớp AsgardRegion đã có thuộc tính autoScaling. Bạn chỉ cần khởi tạo thuộc tính đó và có thể thêm phương thức tiện lợi void autoScaling(Closure closure) { project.configure(autoScaling, closure) } để hỗ trợ cú pháp autoScaling { ... }.

  • project.container tạo một NamedDomainObjectContainer. Cú pháp theo ngữ pháp cho vùng chứa này là someName { ... }; otherName { ... }. Không có cú pháp "danh sách đơn giản".

  • Mã kiểm tra của bạn đặt devPhase v.v. cho autoScalingchứa, không có các thuộc tính này. Đó là lý do tại sao bạn nhận được các thuộc tính động động cảnh báo. Trong cùng { ... } là một khối (không phải là một đóng) và là dư thừa.

Để giải quyết vấn đề danh sách, hoặc xác định một tài sản name cho AsgardAutoScaling và sử dụng thường xuyên NamedDomainObjectContainer cú pháp theo nghĩa đen, hoặc không sử dụng NamedDomainObjectContainer và thực hiện cú pháp của riêng bạn.Ví dụ: bạn có thể khai báo phương thức autoScaling trên AsgardRegion chấp nhận việc đóng, tạo một phiên bản AsgardAutoScaling và thêm nó vào danh sách.

+0

Cảm ơn bạn đã gợi ý! Tôi nghĩ rằng tôi có một cái gì đó làm việc và có một sự hiểu biết tốt hơn về cách chuyển đổi cú pháp tôi muốn mã. – ekaqu

+0

Tôi trễ một chút với bữa tiệc, nhưng làm thế nào để bạn có quyền truy cập vào đối tượng dự án, để tạo vùng chứa, trong một phương thức cấu hình? – kevinmm

0

Câu trả lời trước đã giúp tôi rất nhiều để giải quyết vấn đề của mình. Tôi muốn thêm các đối tượng mở rộng lồng nhau vào tệp build.gradle. Như thế này

family { 
    father { 
     firstName = "Ivan" 
     lastName = "Karamazon" 
    } 
    children { 
     son { 
      firstName = "Alesha" 
      lastName = "Rakitka" 
     } 
    } 
} 

Cuối cùng, tôi có thể làm điều đó và tạo dự án mẫu. Tuy nhiên, các yêu cầu hơi khác nhau để chia sẻ kinh nghiệm của tôi ở đây. Để biết chi tiết, vui lòng trả lời https://stackoverflow.com/a/41491729/3223198 và dự án Github https://github.com/andriipanasiuk/family-gradle-plugin

Các vấn đề liên quan