Use intrinsics in place of predefineds

This change leverages intrinsics in place of the predefined types.
It remains to be seen if we can reach 100% on this, however I am hopeful.
It's also nice that the system will be built "out of itself" with this
approach; in other words, each of the types is simply a Mufile that can
use conditional targeting as appropriate for the given cloud providers.
If we find that this isn't enough, we can always bring back the concept.
This commit is contained in:
joeduffy 2016-12-05 16:13:49 -08:00
parent 4f92a12d30
commit a28f02ce68
9 changed files with 40 additions and 121 deletions

View file

@ -0,0 +1,5 @@
name: mu/autoscaler
description: A service that can automatically scale other services based on policy.
intrinsic: true
properties:

5
lib/mu/container/Mu.yaml Normal file
View file

@ -0,0 +1,5 @@
name: mu/container
description: A Docker/LXC/Windows container.
intrinsic: true
properties:

5
lib/mu/event/Mu.yaml Normal file
View file

@ -0,0 +1,5 @@
name: mu/event
description: An event that may be used to trigger execution of another service.
intrinsic: true
properties:

5
lib/mu/func/Mu.yaml Normal file
View file

@ -0,0 +1,5 @@
name: mu/func
description: A single standalone function for serverless scenarios.
intrinsic: true
properties:

5
lib/mu/gateway/Mu.yaml Normal file
View file

@ -0,0 +1,5 @@
name: mu/gateway
description: An API gateway and load balancer, multiplexing requests over services.
intrinsic: true
properties:

5
lib/mu/volume/Mu.yaml Normal file
View file

@ -0,0 +1,5 @@
name: mu/container
description: A Docker container.
intrinsic: true
properties:

View file

@ -11,7 +11,6 @@ import (
"github.com/marapongo/mu/pkg/ast"
"github.com/marapongo/mu/pkg/compiler/backends/clouds"
"github.com/marapongo/mu/pkg/compiler/core"
"github.com/marapongo/mu/pkg/compiler/predef"
"github.com/marapongo/mu/pkg/diag"
"github.com/marapongo/mu/pkg/encoding"
"github.com/marapongo/mu/pkg/errors"
@ -201,71 +200,14 @@ func (c *awsCloud) genStackServiceTemplates(comp core.Compiland, stack *ast.Stac
// genServiceTemplate creates a CloudFormation resource for a single service.
func (c *awsCloud) genServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.Assert(svc.BoundType != nil)
glog.V(4).Infof("Generating service templates: svc=%v type=%v", svc.Name, svc.BoundType.Name)
// Code-generation differs greatly for the various service types. There are three categories:
// 1) A Mu primitive: these have very specific manifestations to accomplish the desired Mu semantics.
// 2) An AWS-specific extension type: these largely just pass-through CloudFormation goo that we will emit.
// 3) A reference to another Stack: these just instantiate those Stacks and reference their outputs.
switch svc.BoundType {
case predef.Container:
return c.genMuContainerServiceTemplate(comp, stack, svc)
case predef.Gateway:
return c.genMuGatewayServiceTemplate(comp, stack, svc)
case predef.Func:
return c.genMuFuncServiceTemplate(comp, stack, svc)
case predef.Event:
return c.genMuEventServiceTemplate(comp, stack, svc)
case predef.Volume:
return c.genMuVolumeServiceTemplate(comp, stack, svc)
case predef.Autoscaler:
return c.genMuAutoscalerServiceTemplate(comp, stack, svc)
default:
return c.genOtherServiceTemplate(comp, stack, svc)
}
}
func (c *awsCloud) genMuContainerServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.FailMF("%v service types are not yet supported (svc: %v)\n", svc.BoundType.Name, svc.Name)
return nil
}
func (c *awsCloud) genMuGatewayServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.FailMF("%v service types are not yet supported (svc: %v)\n", svc.BoundType.Name, svc.Name)
return nil
}
func (c *awsCloud) genMuFuncServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.FailMF("%v service types are not yet supported (svc: %v)\n", svc.BoundType.Name, svc.Name)
return nil
}
func (c *awsCloud) genMuEventServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.FailMF("%v service types are not yet supported (svc: %v)\n", svc.BoundType.Name, svc.Name)
return nil
}
func (c *awsCloud) genMuVolumeServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.FailMF("%v service types are not yet supported (svc: %v)\n", svc.BoundType.Name, svc.Name)
return nil
}
func (c *awsCloud) genMuAutoscalerServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
util.FailMF("%v service types are not yet supported (svc: %v)\n", svc.BoundType.Name, svc.Name)
return nil
}
// genOtherServiceTemplate generates code for a general-purpose Stack service reference.
func (c *awsCloud) genOtherServiceTemplate(comp core.Compiland, stack *ast.Stack, svc *ast.Service) cfResources {
// Instantiate and textually include the BoundStack into our current template.
// Instantiate and textually include the stack into our current template.
// TODO: consider an option where a Stack can become a distinct CloudFormation Stack, and then reference it by
// name. This would be a terrible default, because we'd end up with dozens of CloudFormation Stacks for even
// the simplest of Mu Stacks. Especially because many Mu Stacks are single-Service. Perhaps we could come
// up with some clever default, like multi-Service Mu Stacks map to CloudFormation Stacks, and single-Service
// ones don't, however I'm not yet convinced this is the right path. So, for now, we keep it simple.
util.Assert(svc.BoundType != nil)
glog.V(4).Infof("Generating \"other\" service template: svc=%v type=%v", svc.Name, svc.BoundType.Name)
glog.V(4).Infof("Generating service template: svc=%v type=%v", svc.Name, svc.BoundType.Name)
if svc.BoundType.Intrinsic {
// For intrinsics, generate code for those that we understand; for all others, issue an error.

View file

@ -10,7 +10,6 @@ import (
"github.com/marapongo/mu/pkg/ast"
"github.com/marapongo/mu/pkg/compiler/core"
"github.com/marapongo/mu/pkg/compiler/predef"
"github.com/marapongo/mu/pkg/diag"
"github.com/marapongo/mu/pkg/encoding"
"github.com/marapongo/mu/pkg/errors"
@ -35,14 +34,6 @@ func NewBinder(c Compiler) Binder {
// Create a new binder and a new scope with an empty symbol table.
b := &binder{c: c}
b.PushScope()
// And now populate that symbol table with all known predefined Stack types before returning it.
for nm, stack := range predef.Stacks {
sym := NewStackSymbol(nm, stack)
ok := b.RegisterSymbol(sym)
util.AssertMF(ok, "Unexpected Symbol collision when registering predef Stack type %v", nm)
}
return b
}

View file

@ -6,57 +6,13 @@ import (
"github.com/marapongo/mu/pkg/ast"
)
// Stacks contains all of the built-in primitive types known to the Mu compiler.
var Stacks = map[ast.Name]*ast.Stack{
Container.Name: Container,
Gateway.Name: Gateway,
Func.Name: Func,
Event.Name: Event,
Volume.Name: Volume,
Autoscaler.Name: Autoscaler,
}
const namespace = "mu"
const Namespace = "mu"
func muName(nm string) ast.Name {
return ast.Name(Namespace + ast.NameDelimiter + nm)
}
var (
Container = &ast.Stack{
Name: muName("container"),
Intrinsic: true,
Description: "An LXC or Windows container.",
Properties: ast.Properties{},
}
Gateway = &ast.Stack{
Name: muName("gateway"),
Intrinsic: true,
Description: "An API gateway and load balancer, multiplexing requests over services.",
Properties: ast.Properties{},
}
Func = &ast.Stack{
Name: muName("func"),
Intrinsic: true,
Description: "A single standalone function for serverless scenarios.",
Properties: ast.Properties{},
}
Event = &ast.Stack{
Name: muName("event"),
Intrinsic: true,
Description: "An event that may be used to trigger execution of another service.",
Properties: ast.Properties{},
}
Volume = &ast.Stack{
Name: muName("volume"),
Intrinsic: true,
Description: "A volume that stores data and can be mounted by other services.",
Properties: ast.Properties{},
}
Autoscaler = &ast.Stack{
Name: muName("autoscaler"),
Intrinsic: true,
Description: "A service that can automatically scale other services based on policy.",
Properties: ast.Properties{},
}
const (
Autoscaler = namespace + ast.NameDelimiter + "autoscaler"
Container = namespace + ast.NameDelimiter + "container"
Gateway = namespace + ast.NameDelimiter + "gateway"
Func = namespace + ast.NameDelimiter + "func"
Event = namespace + ast.NameDelimiter + "event"
Volume = namespace + ast.NameDelimiter + "volume"
)