17

我正在开发一个与 Asgard(来自 netflix)集成的 gradle 插件(我不知道 groovy,并且刚刚开始使用 gradle)。我希望我的扩展对象对用户来说是这样的:

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"]
        }
      }
    }
  }
}

或者类似的东西。我已经能够通过使 autoScaling 成为一个列表来接近这一点,但是当我尝试从该类中获取一个属性时,它似乎返回一个动态属性而不是值。这是下面的入门插件:

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
}

当我运行任务时,这是我在日志中看到的:

$  ./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 "AsgardRegion_Decorated@65087be0", value: "test".
Deprecated dynamic property: "min" on "AsgardRegion_Decorated@65087be0", value: "3".
Deprecated dynamic property: "max" on "AsgardRegion_Decorated@65087be0", value: "6".
Deprecated dynamic property: "availabilityZones" on "AsgardRegion_Decorated@65087be0", value: "[us-east-1a, us-east-1...".
Deprecated dynamic property: "ami" on "AsgardRegion_Decorated@65087be0", value: "Base AMI 2013-07-11".
Deprecated dynamic property: "instanceType" on "AsgardRegion_Decorated@65087be0", value: "m3.xlarge".
Deprecated dynamic property: "securityGroups" on "AsgardRegion_Decorated@65087be0", value: "[base, test-application]".
                devPhase
                devPhase test
                devPhase AsgardRegion_Decorated@14860315('devPhase')

BUILD SUCCESSFUL

Total time: 1.996 secs

我对这一切都错了吗?如果不是,我如何从动态属性中获取值(尝试获取和值,但这些似乎不起作用)。

感谢您花时间阅读本文。

根据@peter-niederwieser 反馈进行编辑

感谢 peter-niederwieser 的提示。在听取了您的建议并查看了关闭的工作原理后,我想我对如何着手去做我想做的事情有了更好的理解。

这是插件的语法:

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"
      }
    }

  }
} 

支持这一点的代码可以在这里找到:

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
}

这是我运行时看到的输出:

$  ./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
4

2 回答 2

6

一些提示:

  • 无需添加autoScaling扩展,region因为AsgardRegion该类已经具有autoScaling属性。您只需要初始化该属性,并可能添加一个void autoScaling(Closure closure) { project.configure(autoScaling, closure) }方便的方法来支持该autoScaling { ... }语法。

  • project.container创建一个NamedDomainObjectContainer. 此容器的文字语法是someName { ... }; otherName { ... }. 没有“普通列表”语法。

  • 您的容器的测试代码集devPhase等,它没有这些属性。这就是您收到动态属性警告的原因。最里面的是一个块(不是闭包)并且是多余的。autoScaling { ... }

要解决列表问题,要么定义name属性AsgardAutoScaling并使用常规NamedDomainObjectContainer文字语法,要么不使用NamedDomainObjectContainer并实现自己的语法。例如,您可以声明一个接受闭包的autoScaling方法AsgardRegion,创建 的实例AsgardAutoScaling并将其添加到列表中。

于 2013-07-13T09:30:20.303 回答
1

以前的答案对我解决问题有很大帮助。我想将嵌套扩展对象添加到build.gradle文件中。像这样

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

最后,我能够做到这一点并创建了示例项目。但是,要求略有不同,所以在这里分享我的经验。有关详细信息,请参阅 SO 回答https://stackoverflow.com/a/41491729/3223198和 Github 项目https://github.com/andriipanasiuk/family-gradle-plugin

于 2017-01-05T18:21:02.283 回答