-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #210 from scottyw/foobernetes
Foobernetes example workflow and plugin
- Loading branch information
Showing
12 changed files
with
738 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ build | |
tmp/ | ||
LICENSE_TMPFILE.txt | ||
*.db | ||
deployment.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package foobernetes | ||
|
||
import ( | ||
"github.com/lyraproj/lyra/cmd/goplugin-foobernetes/resource" | ||
"github.com/lyraproj/pcore/pcore" | ||
"github.com/lyraproj/pcore/px" | ||
"github.com/lyraproj/servicesdk/grpc" | ||
"github.com/lyraproj/servicesdk/service" | ||
) | ||
|
||
// Start the Foobernetes example plugin running | ||
func Start() { | ||
pcore.Do(func(c px.Context) { | ||
s := Server(c) | ||
grpc.Serve(c, s) | ||
}) | ||
} | ||
|
||
// Server returns the built server to be served | ||
func Server(c px.Context) *service.Server { | ||
sb := service.NewServiceBuilder(c, "Foobernetes") | ||
|
||
evs := sb.RegisterTypes("Foobernetes", resource.LoadBalancer{}) | ||
sb.RegisterHandler("Foobernetes::LoadBalancerHandler", &resource.LoadBalancerHandler{}, evs[0]) | ||
|
||
evs = sb.RegisterTypes("Foobernetes", resource.WebServer{}) | ||
sb.RegisterHandler("Foobernetes::WebServerHandler", &resource.WebServerHandler{}, evs[0]) | ||
|
||
evs = sb.RegisterTypes("Foobernetes", resource.Instance{}) | ||
sb.RegisterHandler("Foobernetes::InstanceHandler", &resource.InstanceHandler{}, evs[0]) | ||
|
||
return sb.Server() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/hashicorp/go-hclog" | ||
"github.com/lyraproj/lyra/cmd/goplugin-foobernetes/foobernetes" | ||
) | ||
|
||
func main() { | ||
hclog.DefaultOptions = &hclog.LoggerOptions{ | ||
Name: "Puppet", | ||
Level: hclog.Debug, | ||
JSONFormat: true, | ||
IncludeLocation: false, | ||
Output: os.Stderr, | ||
} | ||
foobernetes.Start() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package resource | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/go-hclog" | ||
) | ||
|
||
var ip int | ||
|
||
// Instance is a virtual machine on which the app or database can be deployed | ||
type Instance struct { | ||
InstanceID *string | ||
InstanceIP *string | ||
Location *string | ||
Image string | ||
Config *map[string]string | ||
Cpus int | ||
Memory string | ||
} | ||
|
||
// InstanceHandler is used to perform CRUD operations on a Instance resource | ||
type InstanceHandler struct{} | ||
|
||
// Create a new resource | ||
func (*InstanceHandler) Create(desiredState *Instance) (*Instance, string, error) { | ||
hclog.Default().Debug("Creating Instance", "desiredState", desiredState) | ||
|
||
// The cloud creates the resource and allocates an ID that can be used to read it in the future | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
cloudAllocatedID := fmt.Sprintf("i-%d", randomInt()) | ||
d.Instances[cloudAllocatedID] = desiredState | ||
|
||
// Update the desired state with values provided by the cloud | ||
ip++ | ||
ipAddress := fmt.Sprintf("10.0.0.%d", ip) | ||
desiredState.InstanceID = &cloudAllocatedID | ||
desiredState.InstanceIP = &ipAddress | ||
|
||
return desiredState, cloudAllocatedID, nil | ||
} | ||
|
||
// Read an existing resource | ||
func (*InstanceHandler) Read(externalID string) (*Instance, error) { | ||
hclog.Default().Debug("Reading Instance", "externalID", externalID) | ||
|
||
// Read the actual state of the resource from the cloud | ||
// The external ID passed here is the same one that is returned at creation time | ||
d := loadFakeCloudData() | ||
actualState := d.Instances[externalID] | ||
|
||
return actualState, nil | ||
} | ||
|
||
// Update an existing resource | ||
func (*InstanceHandler) Update(externalID string, desiredState *Instance) (*Instance, error) { | ||
hclog.Default().Debug("Updating Instance", "externalID", externalID, "desiredState", desiredState) | ||
|
||
// The cloud updates the resource based on its ID | ||
// Update is not allowed to change the external ID | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
|
||
// Update the desired state with values provided by the cloud | ||
actualState := d.Instances[externalID] | ||
desiredState.InstanceID = actualState.InstanceID | ||
desiredState.InstanceIP = actualState.InstanceIP | ||
d.Instances[externalID] = desiredState | ||
|
||
return desiredState, nil | ||
} | ||
|
||
// Delete an existing resource | ||
func (*InstanceHandler) Delete(externalID string) error { | ||
hclog.Default().Debug("Deleting Instance:", "externalID", externalID) | ||
|
||
// The cloud deletes the resource based on its ID | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
delete(d.Instances, externalID) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package resource | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/go-hclog" | ||
) | ||
|
||
// LoadBalancer distributes traffic to web servers | ||
type LoadBalancer struct { | ||
LoadBalancerID *string | ||
LoadBalancerIP *string | ||
Location *string | ||
Replica *bool | ||
WebServerIDs []string | ||
Tags *map[string]string | ||
} | ||
|
||
// LoadBalancerHandler is used to perform CRUD operations on a LoadBalancer resource | ||
type LoadBalancerHandler struct{} | ||
|
||
// Create a new resource | ||
func (*LoadBalancerHandler) Create(desiredState *LoadBalancer) (*LoadBalancer, string, error) { | ||
hclog.Default().Debug("Creating LoadBalancer", "desiredState", desiredState) | ||
|
||
// The cloud creates the resource and allocates an ID that can be used to read it in the future | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
cloudAllocatedID := fmt.Sprintf("lb-%d", randomInt()) | ||
d.LoadBalancers[cloudAllocatedID] = desiredState | ||
|
||
// Update the desired state with values provided by the cloud | ||
desiredState.LoadBalancerID = &cloudAllocatedID | ||
|
||
return desiredState, cloudAllocatedID, nil | ||
} | ||
|
||
// Read an existing resource | ||
func (*LoadBalancerHandler) Read(externalID string) (*LoadBalancer, error) { | ||
hclog.Default().Debug("Reading LoadBalancer", "externalID", externalID) | ||
|
||
// Read the actual state of the resource from the cloud | ||
// The external ID passed here is the same one that is returned at creation time | ||
d := loadFakeCloudData() | ||
actualState := d.LoadBalancers[externalID] | ||
|
||
return actualState, nil | ||
} | ||
|
||
// Update an existing resource | ||
func (*LoadBalancerHandler) Update(externalID string, desiredState *LoadBalancer) (*LoadBalancer, error) { | ||
hclog.Default().Debug("Updating LoadBalancer", "externalID", externalID, "desiredState", desiredState) | ||
|
||
// The cloud updates the resource based on its ID | ||
// Update is not allowed to change the external ID | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
|
||
// Update the desired state with values provided by the cloud | ||
actualState := d.LoadBalancers[externalID] | ||
desiredState.LoadBalancerID = actualState.LoadBalancerID | ||
d.LoadBalancers[externalID] = desiredState | ||
|
||
return desiredState, nil | ||
} | ||
|
||
// Delete an existing resource | ||
func (*LoadBalancerHandler) Delete(externalID string) error { | ||
hclog.Default().Debug("Deleting LoadBalancer:", "externalID", externalID) | ||
|
||
// The cloud deletes the resource based on its ID | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
delete(d.LoadBalancers, externalID) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package resource | ||
|
||
import ( | ||
"encoding/json" | ||
"io/ioutil" | ||
"math/rand" | ||
"os" | ||
"time" | ||
) | ||
|
||
type deployment struct { | ||
LoadBalancers map[string]*LoadBalancer | ||
WebServers map[string]*WebServer | ||
Instances map[string]*Instance | ||
} | ||
|
||
var filename = "deployment.json" | ||
|
||
func loadFakeCloudData() deployment { | ||
var d deployment | ||
bs, err := ioutil.ReadFile(filename) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
d.LoadBalancers = make(map[string]*LoadBalancer) | ||
d.WebServers = make(map[string]*WebServer) | ||
d.Instances = make(map[string]*Instance) | ||
return d | ||
} | ||
panic(err) | ||
} | ||
err = json.Unmarshal(bs, &d) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return d | ||
} | ||
|
||
func saveFakeCloudData(d deployment) { | ||
bs, err := json.MarshalIndent(&d, "", " ") | ||
if err != nil { | ||
panic(err) | ||
} | ||
err = ioutil.WriteFile(filename, bs, os.ModePerm) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func randomInt() int { | ||
s1 := rand.NewSource(time.Now().UnixNano()) | ||
r1 := rand.New(s1) | ||
return r1.Int() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package resource | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/go-hclog" | ||
) | ||
|
||
// WebServer handles HTTP requests targetting the app | ||
type WebServer struct { | ||
WebServerID *string | ||
Port int | ||
AppServers []string | ||
} | ||
|
||
// WebServerHandler is used to perform CRUD operations on a WebServer resource | ||
type WebServerHandler struct{} | ||
|
||
// Create a new resource | ||
func (*WebServerHandler) Create(desiredState *WebServer) (*WebServer, string, error) { | ||
hclog.Default().Debug("Creating WebServer", "desiredState", desiredState) | ||
|
||
// The cloud creates the resource and allocates an ID that can be used to read it in the future | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
cloudAllocatedID := fmt.Sprintf("ws-%d", randomInt()) | ||
d.WebServers[cloudAllocatedID] = desiredState | ||
|
||
// Update the desired state with values provided by the cloud | ||
desiredState.WebServerID = &cloudAllocatedID | ||
|
||
return desiredState, cloudAllocatedID, nil | ||
} | ||
|
||
// Read an existing resource | ||
func (*WebServerHandler) Read(externalID string) (*WebServer, error) { | ||
hclog.Default().Debug("Reading WebServer", "externalID", externalID) | ||
|
||
// Read the actual state of the resource from the cloud | ||
// The external ID passed here is the same one that is returned at creation time | ||
d := loadFakeCloudData() | ||
actualState := d.WebServers[externalID] | ||
|
||
return actualState, nil | ||
} | ||
|
||
// Update an existing resource | ||
func (*WebServerHandler) Update(externalID string, desiredState *WebServer) (*WebServer, error) { | ||
hclog.Default().Debug("Updating WebServer", "externalID", externalID, "desiredState", desiredState) | ||
|
||
// The cloud updates the resource based on its ID | ||
// Update is not allowed to change the external ID | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
|
||
// Update the desired state with values provided by the cloud | ||
actualState := d.WebServers[externalID] | ||
desiredState.WebServerID = actualState.WebServerID | ||
d.WebServers[externalID] = desiredState | ||
|
||
return desiredState, nil | ||
} | ||
|
||
// Delete an existing resource | ||
func (*WebServerHandler) Delete(externalID string) error { | ||
hclog.Default().Debug("Deleting WebServer:", "externalID", externalID) | ||
|
||
// The cloud deletes the resource based on its ID | ||
d := loadFakeCloudData() | ||
defer saveFakeCloudData(d) | ||
delete(d.WebServers, externalID) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,7 @@ aws: | |
department: engineering | ||
project: incubator | ||
lifetime: 1h | ||
|
||
foobernetes: | ||
lb_policy: "rr" | ||
in_production: false |
Oops, something went wrong.