Commit graph

6540 commits

Author SHA1 Message Date
joeduffy 68181fd0fd Eliminate <>s in cap names
I wasn't sure at first how we'd distinguish between strings and cap names.
At first, I thought we'd need special syntax, e.g. `<vpn>`; however, now I
am leaning towards a "type inference" approach, where we will interpret the
string as a cap name rather than string if that's what the target property
expects.  Although this isn't quite as explicitly typed, that's probably a
good thing in this case, as it eliminates verbosity and weird characters.
2016-11-29 14:48:55 -08:00
joeduffy b7b1c5a715 Add readonly annotations on relevant AWS properties 2016-11-29 14:36:07 -08:00
joeduffy bccda1ee29 Nit-rename a variable 2016-11-29 14:32:02 -08:00
joeduffy 787ece1058 Log stack properties (under v=7, extreme verbosity) 2016-11-29 14:31:31 -08:00
joeduffy 2238a95502 Add the notion of "perturbing" properties
This change introduces the notion of "perturbing" properties.  Changing
one of these impacts the live service, possibly leading to downtime.  As
such, we will likely encourage blue/green deployments of them just to be
safe.  Note that this is really just a placeholder so I can keep track of
metadata as we go, since AWS CF has a similar notion to this.

I'm not in love with the name.  I considered `interrupts`, however,
I must admit I liked that `readonly` and `perturbs` are symmetric in
the number of characters (meaning stuff lines up nicely...)
2016-11-29 14:29:34 -08:00
joeduffy 182ae190f1 Use Go template whitespace trimming on AWS templates
To avoid injecting needless whitespace -- which is unfortunately meaningful
in YAML -- we need to use the new "-" trimming operators, available in Go 1.6.
2016-11-29 14:22:09 -08:00
joeduffy c1b5239667 Detect target cloud earlier on
This change detects the target cloud earlier on in the compilation process.
Prior to this change, we didn't know this information until the backend code-generation.
Clearly we need to know this at least by then, however, templates can specialize on this
information, so we actually need it sooner.  This change moves it into the frontend part.

Note that to support this we now eliminate the ability to specify target clusters in
the Mufile alone.  That "feels" right to me anyway, since Mufiles are supposed to be
agnostic to their deployment environment, other than template specialization.  Instead,
this information can come from the CLI and/or the workspace settings file.
2016-11-29 13:42:39 -08:00
joeduffy 89d9269377 Bind dependencies that have no Stacks
In some cases, a dependency will resolve to a diag.Document, rather than
a fully instantiated ast.Stack (in fact, that is the common case).  The
binder needs to detect and tolerate this situation.
2016-11-29 13:04:36 -08:00
joeduffy e68ee3523d Project more EC2 Mu Stacks
This change projects several EC2 Mu stacks that are required for Mu cluster
bootstrapping.  This includes:

        - aws/ec2/internetGateway
        - aws/ec2/route
        - aws/ec2/routeTable
        - aws/ec2/securityGroup
        - aws/ec2/subnet
        - aws/ec2/vpc
        - aws/ec2/vpcGatewayAttachment

This is still not complete, and in fact some of these reference other EC2
Stacks that do not yet exist.  But we're getting a bit closer...
2016-11-29 12:37:52 -08:00
joeduffy 9326607c46 Add the notion of readonly properties
This change adds the notion of readonly properties to stacks.  Although these
*can* be "changed", doing so implies recreation of the resources all over again.
As a result, all dependents must be recreated, in a cascading manner.
2016-11-29 12:36:02 -08:00
joeduffy f9a1cf400e Add DependsOn support in CF template generation 2016-11-29 12:23:46 -08:00
joeduffy fb1a6ec4d2 Add a "require" template function
The "require" template function simply checks a condition and, if it
is false, issues an error and quits template processing immediately.
This is useful for concisely encoding validation logic.
2016-11-29 12:12:53 -08:00
joeduffy 6d3296b65f Permit explicit listing of properties to map
In some cases, we actually want to suppress auto-mapping for all or
most of the properties.  In those cases, it's easier to specify those
that we *do* want rather than the ones we *do not* want.  Now with
properties, skipProperties, and extraProperties, we have all the
necessary flexibility to control auto-mapping for CF templates.
2016-11-29 12:04:05 -08:00
joeduffy 4b58c862a4 Add a "has" template function
The new "has" function lets templates conveniently check the existence of
keys in property bag-like maps.  For example:

        {{if has .Properties "something"}}
                ...
        {{end}}
2016-11-29 11:43:20 -08:00
joeduffy 9a962b2014 Add skipProperties and extraProperties to aws/cf extension provider
Most properties in CF templates are auto-mapped by the aws/cf extension
provider.  However, sometimes we want to inject extra properties that are
outside of that auto-mapping (like our convenient shortcut for supplying
name to mean adding a "Name=v" tag).  And sometimes we want to skip auto-
mapping for certain properties (like our capability-based approach to
passing service references, versus string IDs).
2016-11-29 11:31:58 -08:00
joeduffy d722cc284f Inject the availability zone from cluster settings 2016-11-28 16:30:32 -08:00
joeduffy f511d30a37 Project the AWS::EC2::VPC resource type into Mu 2016-11-28 16:28:23 -08:00
joeduffy 6f572a6a5b Add an initial whack at a cluster Mufile
This change adds a super simple initial whack at a basic cluster topology
comprised of VPC, subnet, internet gateway, attachments, and route tables.
This is actually written in Mu itself, and I am committing this early, since
there are quite a few features required before we can actually make progress
getting this up and running.
2016-11-28 16:18:38 -08:00
joeduffy 9acfd18dc2 Add the target architecture to the rendering context
This allows templates to switch on the target cloud and do the right thing.
2016-11-28 15:15:49 -08:00
joeduffy 5233b2bcbe Add a "panic" template function
This introduces a "panic" template function, so that templates may abandon
evaluation if something unexpected occurs.  It accepts a string, indicating
the error, and optional arguments, if the string is to be formatted.

For example:

        {{if eq .Target "aws"}}
                ...
        {{else}}
                {{panic "Unrecognized cloud target: %v" .Target}}
        {{end}}
2016-11-28 14:56:43 -08:00
joeduffy 63ddbc6e7a Add an "include" template function
This lets YAML files include others, often conditionally, based on things
like the cloud target.  For example, I am currently using this to define the
overall cluster stack by doing things like:

        name: mu/cluster
        services:
        {{if eq .Target "aws"}}
                {{include "Mu-aws.yaml" | indent 4}}
        {{else}}
                ...
        {{end}}
2016-11-28 14:54:41 -08:00
joeduffy 1302fc8a47 Add rudimentary template expansion
This change performs template expansion both for root stack documents in
addition to the transitive closure of dependencies.  There are many ongoing
design and implementation questions about how this should actually work;
please see marapongo/mu#7 for a discussion of them.
2016-11-25 12:58:29 -08:00
joeduffy ffae234af0 Add a Mu.yaml to the MongoDB/Twilio example 2016-11-23 16:28:00 -08:00
joeduffy 6e77e0f462 Sketch out some cross-cloud abstraction thinking 2016-11-23 16:20:40 -08:00
joeduffy e37aa602c9 Add an aws/dynamodb/table type 2016-11-23 16:07:26 -08:00
joeduffy bbfbe61d43 Mention ln -s for the Mu runtime/library 2016-11-23 14:22:42 -08:00
joeduffy c1c43c7907 Use /usr/local/mu as the default install path 2016-11-23 14:18:18 -08:00
joeduffy 0d6208bb00 Simplify cf/template extension provider
For now, we can simply auto-map the Mu properties to CF properties,
eliminating the need to manually map them in the templates.  Eventually
we'll want more sophistication here to control various aspects of the CF
templates, but this eliminates a lot of tedious manual work in the meantime.
2016-11-23 14:16:35 -08:00
joeduffy a1660c1298 Add building and testing instructions 2016-11-23 12:41:30 -08:00
joeduffy 925ee92c60 Annotate a bunch of TODOs with work item numbers 2016-11-23 12:30:02 -08:00
joeduffy d26c1e395a Implement diag.Diagable on ast.Workspace and ast.Stack
The only two AST nodes that track any semblance of location right now
are ast.Workspace and ast.Stack.  This is simply because, using the standard
JSON and YAML parsers, we aren't given any information about the resulting
unmarshaled node locations.  To fix that, we'll need to crack open the parsers
and get our hands dirty.  In the meantime, we can crudely implement diag.Diagable
on ast.Workspace and ast.Stack, however, to simply return their diag.Documents.
2016-11-23 07:54:40 -08:00
joeduffy 2b385b2e20 Prepare for better diagnostics
This change adds a new Diagable interface from which you can obtain
a diagnostic's location information (Document and Location).  A new
At function replaces WithDocument, et al., and will be used soon to
permit all arbitrary AST nodes to report back their position.
2016-11-23 07:44:03 -08:00
joeduffy e02921dc35 Finish dependency and type binding
This change completes the implementation of dependency and type binding.
The top-level change here is that, during the first semantic analysis AST walk,
we gather up all unknown dependencies.  Then the compiler resolves them, caching
the lookups to ensure that we don't load the same stack twice.  Finally, during
the second and final semantic analysis AST walk, we populate the bound nodes
by looking up what the compiler resolved for us.
2016-11-23 07:26:45 -08:00
joeduffy c478ffbe40 Preserve blank ""s in RefParts
This changes the logic when parsing RefParts so that we can actually
round-trip them faithfully when required.  To do this, by default we
preserve blank ""s in the RefPart fields that are legally omitted from
the Ref string.  Then, there is a Defaults() method that can populate
the missing fields with the defaults if desired.
2016-11-22 17:24:49 -08:00
joeduffy 12eb91bcbb Fix a typo that crept in 2016-11-22 17:07:10 -08:00
joeduffy c84512510a Implement dependency versions
This change implements dependency versions, including semantic analysis, per the
checkin 83030685c3.

There's quite a bit in here but at a top-level this parses and validates dependency
references of the form

        [[proto://]base.url]namespace/.../name[@version]

and verifies that the components are correct, as well as binding them to symbols.

These references can appear in two places at the moment:

* Service types.
* Cluster dependencies.

As part of this change, a number of supporting changes have been made:

* Parse Workspaces using a full-blown parser, parser analysis, and semantic analysis.
  This allows us to share logic around the validation of common AST types.  This also
  moves some of the logic around loading workspace.yaml files back to the parser, where
  it can be unified with the way we load Mu.yaml files.

* New ast.Version and ast.VersionSpec types.  The former represents a precise version
  -- either a specific semantic version or a short or long Git SHA hash -- and the
  latter represents a range -- either a Version, "latest", or a semantic range.

* New ast.Ref and ast.RefParts types.  The former is an unparsed string that is
  thought to contain a Ref, while the latter is a validated Ref that has been parsed
  into its components (Proto, Base, Name, and Version).

* Added some type assertions to ensure certain structs implement certain interfaces,
  to speed up finding errors.  (And remove the coercions that zero-fill vtbl slots.)

* Be consistent about prefixing error types with Error or Warning.

* Organize the core compiler driver's logic into three methods, FE, sema, and BE.

* A bunch of tests for some of the above ...  more to come in an upcoming change.
2016-11-22 16:58:23 -08:00
joeduffy 83030685c3 Articulate how dependency versioning works
I've gone backwards and forwards on the design for dependency version
management.  However, I think what's written in this commit represents
a pretty sane "sweet spot" between all available options.

In a nutshell, anytime reference to a stack type in your Mufile is a
full-blown StackRef; in other words, it has a protocol (e.g., "https://"),
a base URL (e.g., "hub.mu.com/"), a name (e.g., "aws/s3/bucket"), and a
version ("@^1.0.6").  Each reference carries all of these components.

For convenience, you may omit the components.  In that case, Mu chooses
reasonable defaults:

* "https://" as the default protocol (or "git://"; this is TBD).
* "hub.mu.com/" as the default base URL.
* "@latest" as the default version number.

Note that a version can be "latest" to mean "tip", a specific SHA hash
to pin to a precise version, or a semantic version number/range.

I had originally shied away from specifying versions inline as you reference
stacks in your Mufile, and was leaning towards an explicit dependencies
section, however I was swayed for two reasons:

1. It's very common to only consume a given stack once in a file.  Needing
   to specify it in two places each time is verbose and violates DRY.

2. We have decided that each Mufile stands on its own and forms the unit
   of distribution.  I had previously thought we might move dependencies
   out of Mufiles into a "package manager" specification.  Lacking that,
   there is even less reason to call them out in a dedicated section.

Now, managing all these embedded version numbers across multiple stacks in
a single workspace would have been annoying.  (Many edits for a single
version bump.)  Instead, I've added provisions for storing this in your
workspace.yaml file.  The way it works is if any StackRef lacks a version
number, before defaulting to "@latest" we check the workspace.yaml file and,
if a default is found in there, we will use it.  For example:

        dependencies:
                aws/s3/bucket: ^1.0.6

The provision for pinning an entire namespace is also preserved.  E.g.:

        dependencies:
                aws/...: ^1.0.6
2016-11-22 13:22:29 -08:00
joeduffy 6f99088e2b Add scaffolding for the AWS ECS scheduler backend
Right now, the AWS ECS scheduler simply passes through to the underlying
AWS cloud provider.  However, now we have the necessary hooks to start
incrementally recognizing stack types and emitting specialized code for
them (e.g., starting with mu/container).
2016-11-22 12:37:14 -08:00
joeduffy 5a8069e2fe Fix a silly message 2016-11-22 11:25:51 -08:00
joeduffy 1c5afa2b63 Add code-generation for Stack references
This change adds code-generation for Stack references other than the built-in types.
This permits you to bind to a dependency and have it flow all the way through to the
code-generation phases.  It still most likely bottoms out on something that fails,
however for pure AWS resources like aws/s3/bucket everything now works.
2016-11-22 11:13:16 -08:00
joeduffy 5f3af891f7 Support Workspaces
This change adds support for Workspaces, a convenient way of sharing settings
among many Stacks, like default cluster targets, configuration settings, and the
like, which are not meant to be distributed as part of the Stack itself.

The following things are included in this checkin:

* At workspace initialization time, detect and parse the .mu/workspace.yaml
  file.  This is pretty rudimentary right now and contains just the default
  cluster targets.  The results are stored in a new ast.Workspace type.

* Rename "target" to "cluster".  This impacts many things, including ast.Target
  being changed to ast.Cluster, and all related fields, the command line --target
  being changed to --cluster, various internal helper functions, and so on.  This
  helps to reinforce the desired mental model.

* Eliminate the ast.Metadata type.  Instead, the metadata moves directly onto
  the Stack.  This reflects the decision to make Stacks "the thing" that is
  distributed, versioned, and is the granularity of dependency.

* During cluster targeting, add the workspace settings into the probing logic.
  We still search in the same order: CLI > Stack > Workspace.
2016-11-22 10:41:07 -08:00
joeduffy d55acad652 Add a workspace file to our demo
This just sets the default cloud provider to AWS.
2016-11-22 09:50:53 -08:00
joeduffy eb12b7a197 Use precompiled regexps for AWS cloud provider 2016-11-22 09:45:42 -08:00
joeduffy 0f666688bd Add a diag.Sink.Success helper function
This new API cleans up callsites so that they can say

        if d.Success() {
        }

rather than

        if d.Errors() == 0 {
        }
2016-11-22 09:40:09 -08:00
joeduffy 728c22bed1 Remove a useless log message 2016-11-22 09:36:07 -08:00
joeduffy 9120a12134 Initialize the dependency map during compiler creation 2016-11-22 09:33:18 -08:00
joeduffy 4df1ec8c35 Support baseless and baseful package paths
This changes the probing logic for dependency resolution.  The old logic was
inconsistent between the various roots.  The new approach simply prefers locations
with a base URL component -- since they are more specific -- but will allow for
locations missing a base URL component.  This is convenient for developers managing
a workspace where needing to specify the base URL in the path is annoying and
slightly too "opinionated" for my taste (especially for migrating existing services).
2016-11-22 09:28:25 -08:00
joeduffy d79ec0d0c5 Add some handy logging 2016-11-22 09:20:23 -08:00
joeduffy 7f712243f7 Demonstrate hypothetical mu/app type in the demo 2016-11-22 08:58:06 -08:00
joeduffy dc9f7412b0 Add one more name test just for fun 2016-11-21 12:09:51 -08:00