README.md

# Railyard

Railyard combines infrastructure as code and config management as a library
within your Elixir application. It uses a Chef-like syntax to define resources
within modules, which can be "shipped" (see `Railyard.ship/2`) to cloud providers,
SaaS APIs, local configuration, etc.

## Installation

Railyard can be installed by adding `railyard` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:railyard, "~> 0.1.0"}
  ]
end
```

Run `mix deps.get` to pull down the latest dependencies.

# Distillery Plugin

Once installed, you may want to take advantage of the Distillery plugin to automatically
provision cloud instances with your build.

First, make sure that you've defined a `Railyard.Distillery` resource in your infrastructure:

```elixir
defmodule MyApp.Infrastructure
  use Railyard.Dsl

  resource :distillery, Railyard.Distillery do
    # The Railyard.Distillery module docs describe how to set up this resource
  end
end
```

Install the plugin into an environment in your `rel/config.exs` file, and specify the
Distillery resource that you're bundling:

```elixir
environment :prod do
  # ... Distillery config

  plugin Railyard.Distillery.Plugin, resource: {MyApp.Infrastructure, :distillery}
end
```

Distillery will now handle packaging and uploading releases in a way that will allow
instances to automatically fetch and install releases during provisioning. Simply run
`MIX_ENV=prod mix release` to build and upload a new version.

## Getting Started

You're in the right place. The rest of this document will help you get oriented,
and set up with some basic config management and infrastructure as code. For reference material,
the `Railyard` and `Railyard.Dsl` modules are the best place to go.

To get started with Railyard, there are a couple of terms that you will need to know.

### Resource Spec

When writing code with Railyard, you will be writing **resource specs**. A resource spec
describes what a resource should look like at a particular moment in time, but does not
generally describe how to get there, or what changes to make along the way.

A resource spec looks something like this:

```elixir
resource :my_file, Railyard.Fs.File do
  path "./my_file.txt"
  contents "Hello, world!"
end
```

Resource specs are written inside resource modules. Speaking of which...

### Resource Module

A **resource module** is an Elixir module that has used `Railyard.Dsl` to define infrastructure
components. Resource modules are the entrypoint for instantiating the infrastructure
described in the resource specs. To elaborate on the above example...

```elixir
defmodule MyFiles do
  use Railyard.Dsl

  resource :my_file, Railyard.Fs.File do
    path "./my_file.txt"
    contents "Hello, world!"
  end
end
```

### Resource

A **resource** is the actual instance of the thing you wanted. A launched and running EC2
instance is a resource. A file on disk is a resource.

A `Resource` is a genserver that supervises that **resource**, and **ships** changes to
those resources.

### Ship

To **ship** a resource requires two pieces: the **resource spec** as described above, and
a set of **bindings**.

To ship the resource module we defined earlier, we would do something like this:

```elixir
MyFiles.ship([])
```

### Resource Provider