Skip to content
This repository has been archived by the owner on May 17, 2020. It is now read-only.

Add basic cluster and API management #16

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
9 changes: 9 additions & 0 deletions cmd/karigo/util/create_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ func CreateServer() *karigo.Server {
ctlNode := karigo.NewNode(&memory.Journal{}, src)
ctlNode.Name = "main_node"

// Cluster control schema
// sc := karigo.ClusterSchema()
// ops := karigo.SchemaToOps(sc)

// err := ctlNode.Apply(ops)
// if err != nil {
// panic(err)
// }

// Register node
server.Nodes["127.0.0.1"] = ctlNode
server.Nodes["localhost"] = ctlNode
Expand Down
20 changes: 18 additions & 2 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ func NewNode(journal Journal, src Source) *Node {

// Node ...
type Node struct {
Name string
Domains []string
Name string

// Run
log Journal
Expand Down Expand Up @@ -349,3 +348,20 @@ func (n *Node) Handle(r *Request) *jsonapi.Document {

return doc
}

// AddSource adds a source to the node.
//
// name is currently ignored and only one source can be added. Adding a second
// source simply overrides the first one.
//
// TODO Add support for multiple sources.
func (n *Node) AddSource(name string, s Source) {
n.main = source{
src: s,
}
}

// RegisterJournal ...
func (n *Node) RegisterJournal(j Journal) {
n.log = j
}
182 changes: 182 additions & 0 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,100 @@ func FirstSchema() *jsonapi.Schema {
return schema
}

// ClusterSchema ...
func ClusterSchema() *jsonapi.Schema {
schema := &jsonapi.Schema{}

typ, err := jsonapi.BuildType(server{})
if err != nil {
panic(err)
}

err = schema.AddType(typ)
if err != nil {
panic(err)
}

typ, err = jsonapi.BuildType(node{})
if err != nil {
panic(err)
}

err = schema.AddType(typ)
if err != nil {
panic(err)
}

typ, err = jsonapi.BuildType(api{})
if err != nil {
panic(err)
}

err = schema.AddType(typ)
if err != nil {
panic(err)
}

typ, err = jsonapi.BuildType(domain{})
if err != nil {
panic(err)
}

err = schema.AddType(typ)
if err != nil {
panic(err)
}

return schema
}

// server ...
type server struct {
ID string `json:"id" api:"0_servers"`

// Attributes
// Name string `json:"name" api:"attr"`
Address string `json:"address" api:"attr"`

// Relationships
Nodes []string `json:"nodes" api:"rel,0_nodes,server"`
}

// node ...
type node struct {
ID string `json:"id" api:"0_nodes"`

// Attributes
Address string `json:"address" api:"attr"`

// Relationships
Server string `json:"server" api:"rel,0_servers,nodes"`
API string `json:"api" api:"rel,0_apis,nodes"`
}

// api ...
type api struct {
ID string `json:"id" api:"0_apis"`

// Attributes
// Address string `json:"address" api:"attr"`

// Relationships
Nodes []string `json:"nodes" api:"rel,0_nodes,api"`
Domains []string `json:"domains" api:"rel,0_domains,api"`
}

// domain ...
type domain struct {
ID string `json:"id" api:"0_domains"`

// Attributes
Address string `json:"address" api:"attr"`

// Relationships
API string `json:"api" api:"rel,0_apis,domains"`
}

// meta ...
type meta struct {
ID string `json:"id" api:"0_meta"`
Expand Down Expand Up @@ -147,6 +241,49 @@ type op struct {
Version string `json:"version" api:"rel,0_log,ops"`
}

// SchemaToOps returns a slice of operations necessary to recreate the schema.
func SchemaToOps(schema *jsonapi.Schema) []Op {
ops := []Op{}

for _, typ := range schema.Types {
// Add set
ops = append(ops, NewOpAddSet(typ.Name)...)
ops = append(ops, NewOpActivateSet(typ.Name)...)

// Add attributes
for _, attr := range typ.Attrs {
ops = append(ops, NewOpAddAttr(
typ.Name,
attr.Name,
jsonapi.GetAttrTypeString(attr.Type, false),
attr.Nullable,
)...)
ops = append(ops, NewOpActivateAttr(typ.Name, attr.Name)...)
}

// Add relationships
for _, rel := range typ.Rels {
ops = append(ops, NewOpAddRel(
rel.FromType,
rel.FromName,
rel.ToType,
rel.ToName,
rel.ToOne,
rel.FromOne,
)...)

relID := rel.FromType + "_" + rel.FromName
if rel.ToName != "" {
relID += "_" + rel.ToType + "_" + rel.ToName
}

ops = append(ops, NewOpActivateRel(relID)...)
}
}

return ops
}

func handleSchemaChange(s *jsonapi.Schema, r *Request, cp *Checkpoint) {
var (
res jsonapi.Resource
Expand Down Expand Up @@ -246,3 +383,48 @@ func activateRel(s *jsonapi.Schema, res jsonapi.Resource) error {
func deactivateRel(s *jsonapi.Schema, res jsonapi.Resource) {
s.RemoveRel(res.Get("from-type").(string), res.Get("name").(string))
}

// func handleClusterChange(s *jsonapi.Schema, r *Request, cp *Checkpoint) {
// var (
// res jsonapi.Resource
// err error
// )

// res, _ = r.Doc.Data.(jsonapi.Resource)

// if r.Method == "PATCH" {
// // Can only be for activating or deactivating
// // a set, attribute, or relationship.
// if active, ok := res.Get("active").(bool); ok {
// if active {
// switch r.URL.ResType {
// case "0_sets":
// err = activateSet(s, res.GetID())
// case "0_attrs":
// res = cp.Resource(QueryRes{
// Set: "0_attrs",
// ID: res.GetID(),
// })
// err = activateAttr(s, res)
// case "0_rels":
// res = cp.Resource(QueryRes{
// Set: "0_rels",
// ID: res.GetID(),
// })
// err = activateRel(s, res)
// }
// } else {
// switch r.URL.ResType {
// case "0_sets":
// deactivateSet(s, res)
// case "0_attrs":
// deactivateAttr(s, res)
// case "0_rels":
// deactivateRel(s, res)
// }
// }
// }

// cp.Check(err)
// }
// }
4 changes: 4 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ type Server struct {
func (s *Server) Run(port uint) {
s.logger.Info().Str("event", "server_start")

if s.Nodes == nil {
s.Nodes = map[string]*Node{}
}

for _, node := range s.Nodes {
node.logger = s.logger
}
Expand Down