{"id":13463739,"url":"https://github.com/philcali/sbt-aws-plugin","last_synced_at":"2026-01-30T12:11:43.726Z","repository":{"id":10133723,"uuid":"12206382","full_name":"philcali/sbt-aws-plugin","owner":"philcali","description":"A simple AWS EC2 IO inside of an sbt console","archived":false,"fork":false,"pushed_at":"2014-05-02T11:38:29.000Z","size":360,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-29T16:19:45.731Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"gollum/gollum","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/philcali.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-08-19T03:25:14.000Z","updated_at":"2017-01-01T06:04:37.000Z","dependencies_parsed_at":"2022-09-22T06:02:14.487Z","dependency_job_id":null,"html_url":"https://github.com/philcali/sbt-aws-plugin","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philcali%2Fsbt-aws-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philcali%2Fsbt-aws-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philcali%2Fsbt-aws-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/philcali%2Fsbt-aws-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/philcali","download_url":"https://codeload.github.com/philcali/sbt-aws-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245435073,"owners_count":20614823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T14:00:27.736Z","updated_at":"2026-01-30T12:11:43.700Z","avatar_url":"https://github.com/philcali.png","language":"Scala","funding_links":[],"categories":["Tooling"],"sub_categories":["Angular"],"readme":"# AWS EC2 SBT Plugin\n\nThis plugin allows maintaining EC2 environments from inside the sbt console.\nThe plugin is particularly useful for deploying groups of dependent\ncloud servers for tasks like Selenium grid, Akka clusters, Mongo config\nservers, etc.\n\nYou can specify monitoring for a group, and triggers for when they are \"hot\".\nYou can optionally specify a ssh client to run commands on instances.\n\nEssentially, it's possible to build, and deploy to target EC2 environments, via\nan sbt build script we know and love.\n\n## Installation\n\n__build.sbt__\n\n```\naddSbtPlugin(\"com.github.philcali\" % \"sbt-aws-plugin\" % \"0.1.0\")\n```\n\nor via git uri:\n\n```\nlazy val root = project.in( file(\".\") ).dependsOn( awsPlugin )\nlazy val awsPlugin = uri(\"git://github.com/philcali/sbt-aws-plugin\")\n```\n\nAdditional plugin information (like global plugins, etc) can be found\nat the [sbt plugin documentation][1].\n\n## Requirements\n\n- Some accessible [Mongo DB][2]\n- [Amazon AWS account][3], with API access\n\n## Plugin Structure\n\nAt this point in the plugin's life, the main points are:\n\n- Filter AMI's into logical groups\n- Create instances from those AMI's, with customizable groups and types\n- Alert when instances are ready to be operated one\n- Customize an SSH client for an instance\n- Terminate the logical groups\n\nLogical groups are _named_ describeImageRequests, or\n`NamedAwsRequest`s. These are added via the `awsEc2.requests` key.\n\nThe ability to create environment from these logical groups is\ncrucial, and that's where `awsEc2.actions` comes into play. This is a\ncollection of `NamedAwsAction`s.\n\nBuilt-in actions are:\n\n- `test`: Dry runs the request with your filters to \"test\" the result\n- `create`: Creates instances from the logical group\n- `start`: Starts instances from the logical group marked \"stopped\"\n- `stop`: Stops instances from the logical group marked \"running\"\n- `alert`: Watches created instances from the logical group\n- `status`: Checks the status of the group from Amazon\n- `terminate`: Terminates the group\n\nOnce an instance is created or started, the `awsEc2.started` callback is invoked.\nThis callback is particularly useful for mapping elastic IP\naddresses, monitors, and status checks to newly created instances\nin the logical group.\n\nOnce instances are denoted to being _hot_, the `awsEc2.running`\ncallback is invoked. This callback is far more useful as it might\ninvolve organized coupling of two or more logical groups.\n\nFinally, there's the `NamedSshScript`. This is an optional setup, but\nenhances the plugin's automated capabilities with the ability to\nexecute remote commands and file transfers, via ssh and Scala code.\n\n## Ideal Setup\n\n- install sbt-aws-plugin as a global sbt plugin\n- create a `aws.sbt` file in your `~/.sbt/{version}/`, containing your aws credentials, `aws.key` and `aws.secret`\n- create a `ssh.sbt` file in your `~/.sbt/{version}/`, containing your ssh public key path to your aws pem.\n\nNow you can create an EC2 instance to test deployment, integration, etc, for your Apps.\n\n## Learn by Example\n\nIn this example, assume we're building a Selenium test program that\nconnects to a hub, linked by UI nodes, hitting the application server\nwhere your app is deployed.\n\nIt's pretty clear our logical groups here:\n\n- `hub`\n- `nodes`\n- `app`\n\nAssuming our `aws.sbt` contains the credentials, and `ssh.sbt`\ncontains the ssh client info, we need to define the image requests.\n\n- `aws-ec2-request/hub.json`\n\n```\n{\n  \"owners\": [\"your ownerID\", \"someone else's id?\"],\n  \"filters\": [\n    { \"name\": \"tag:Type\", \"value\": \"Selenium Hub\" }\n  ]\n}\n```\n\n- `aws-ec2-request/nodes.json`\n\n```\n{\n  \"owners\": [\"ownerId\"],\n  \"filters\": [\n    { \"name\": \"tag:Type\", \"value\": \"Selenium Nodes\" }\n  ]\n}\n```\n\n- `aws-ec2-request/app.json`\n\n```\n{\n  \"owners\": [\"ownerId\"],\n  \"filters\": [\n    { \"name\": \"name\", \"value\": \"Java7 App Server\" }\n  ]\n}\n```\n\nIt is recommended to customize the `awsEc2.configuredInstance` key, to\nattach instance size, security group, or key pair info for the `create` action.\n\n```\nawsEc2.configuredInstance := {\n  case (\"hub\", image) =\u003e\n  awsEc2.defaultRunRequest(image, \"m1.small\")\n    .withMinCount(1)\n    .withMaxCount(1)\n    .withSecurityGroups(\"Selenium Grid Server\")\n  case (\"nodes\", image) =\u003e\n  awsEc2.defaultRunRequest(image)\n    .withMinCount(1)\n    .withMaxCount(1)\n    .withSecurityGroups(\"UI Group\")\n  case (\"app\", image) =\u003e\n  awsEc2.defaultRunRequest(image, \"m1.small\")\n    .withMinCount(1)\n    .withMaxCount(1)\n    .withSecurityGroups(\"App Group\")\n}\n```\n\nAt this point, you can now run `awsEc2Run create nodes` in the shell,\nand it will create all of the UI node instances. Automatically\ncreating the instances doesn't give us much if they can't wire\nthemselves up to one another. In the Selenium grid architecture,\nthe hub must be running, and nodes connect themselves to it. Let's\ncreate a couple of `NamedSshScript`s to launch the grid and connect\nthe nodes to it.\n\n```\nval seleniumJar = \"java -jar selenium-server.jar\"\n\nawsSsh.scripts += NamedSshScript(\"grid\", execute = {\n  _.exec(s\"${seleniumJar} -role hub \u003e /dev/null \u00262\u003e1 \u0026\")\n})\n\nawsSsh.scripts += NamedSshScript(\"node\", execute = {\n  client =\u003e\n  val query = MongoDBObject(\"group\" -\u003e \"hub\")\n  awsMongo.collection.value.findOne(query) match {\n    case Some(instance) =\u003e\n    val hubUrl = s\"http://${instance(\"publicDns\")}:4444/grid/register\"\n    client.exec(s\"${seleniumJar} -role node -hub ${hubUrl} \u003e /dev/null \u00262\u003e1 \u0026\")\n    case None =\u003e Left(\"Please create the hub \u003e:(\")\n  }\n})\n\nawsSsh.scripts += NamedSshScript(\"deploy\", execute = {\n  sshClient =\u003e\n  val jar = \"~/\" + (jarName in assembly).value\n  val assemblyJar = (outputPath in assembly).value.getAbsolutePath\n\n  sshClient.upload(assemblyJar, jar).right.map {\n    _.exec(\"java -jar \" + jar)\n  }\n})\n```\n\nNow that the scripts are in place, we can execute them when the\ninstance is hot, by tying it in `awsEc2.running`.\n\n```\nawsEc2.running := {\n  instance =\u003e\n  val execute = (script: NamedSshScript) =\u003e {\n    awsSsh.retry(delay = awsEc2.pollingInterval.value) {\n      awsSsh.connectScript(instance, awsSsh.config.value)(script)\n    }\n  }\n  instance.get(\"group\") foreach {\n    case \"hub\" =\u003e\n    awsSsh.scripts.value.find(_.name == \"grid\") foreach (execute)\n    case \"nodes\" =\u003e\n    awsSsh.scripts.value.find(_.name == \"node\") foreach (execute)\n    case _ =\u003e\n    streams.value.log.info(\"Instance is running.\")\n  }\n}\n```\n\nThe running callbacks will fire upon logical group alert:\n\n```\n\u003e awsEc2Run create *\n\u003e awsEc2Run alert hub\n\u003e awsEc2Run alert nodes\n\u003e awsEc2Run alert app\n\u003e assembly\n\u003e awsSshRun deploy app\n```\n\nAssuming that `test:run` will launch the Selenium test suite with an\narg to take in the hub url and app url:\n\n```\n\u003e awsEc2Run status app\n\u003e awsEc2Run status hub\n```\n\nThat'll give you the public DNS of the hub and app, respectively.\n\n```\n\u003e test:run http://hubPublicDns:4444/wd/hub http://appPublicDns\n```\n\nRun it as much as you like until you are ready to destroy the groups.\n\n```\n\u003e awsEc2Run terminate *\n```\n\nObviously, this process could be a improved a bit if the runner could\naccess the mongo ec2 instance collection.\n\n[1]: http://www.scala-sbt.org/release/docs/Extending/Plugins\n[2]: http://www.mongodb.com/\n[3]: http://aws.amazon.com/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilcali%2Fsbt-aws-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphilcali%2Fsbt-aws-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilcali%2Fsbt-aws-plugin/lists"}