v3 proto: vtctld & zktopo integration

This commit is contained in:
Sugu Sougoumarane 2015-01-04 14:25:46 -08:00
Родитель b80eaa5a43
Коммит 2c06df4e5e
13 изменённых файлов: 208 добавлений и 33 удалений

Просмотреть файл

@ -0,0 +1,25 @@
<html>
<head>
<title>VSchema view</title>
<style>
html {font-family: sans-serif;}
</style>
</head>
<body>
{{if .Error}}
<h2>Error</h2>
{{.Error}}
{{else}}
<h2>Success</h2>
{{end}}
<pre>{{.Output}}</pre>
<form method="post">
Upload VSchema<br><textarea name="vschema" cols=80 rows=30>{{.Input}}</textarea><br>
<input type="submit" value="Submit">
</form>
</body>
</html>

Просмотреть файл

@ -339,6 +339,8 @@ var indexContent = IndexContent{
ToplevelLinks: map[string]string{
"DbTopology Tool": "/dbtopo",
"Serving Graph": "/serving_graph",
"Schema editor": "/schema_editor",
"Schema view": "/vschema",
},
}
var ts topo.Server
@ -444,10 +446,6 @@ func main() {
templateLoader.ServeTemplate("index.html", indexContent, w, r)
})
http.HandleFunc("/schema_editor/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, *schemaEditorDir+r.URL.Path)
})
// keyspace actions
http.HandleFunc("/keyspace_actions", func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
@ -560,6 +558,40 @@ func main() {
templateLoader.ServeTemplate("serving_graph.html", servingGraph, w, r)
})
// vschema editor
http.HandleFunc("/schema_editor/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, *schemaEditorDir+r.URL.Path)
})
// vschema viewer
http.HandleFunc("/vschema", func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
httpError(w, "cannot parse form: %s", err)
return
}
schemafier, ok := wr.TopoServer().(topo.Schemafier)
if !ok {
httpError(w, "%s", fmt.Errorf("%T doesn's support schemafier API", wr.TopoServer()))
}
var data struct {
Error error
Input, Output string
}
switch r.Method {
case "POST":
data.Input = r.FormValue("vschema")
data.Error = schemafier.SaveVSchema(data.Input)
}
vschema, err := schemafier.GetVSchema()
if err != nil {
if data.Error == nil {
data.Error = fmt.Errorf("Error fetching schema: %s", err)
}
}
data.Output = vschema
templateLoader.ServeTemplate("vschema.html", data, w, r)
})
// redirects for explorers
http.HandleFunc("/explorers/redirect", func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
@ -695,5 +727,6 @@ func main() {
}
http.Redirect(w, r, target, http.StatusFound)
})
servenv.RunDefault()
}

Просмотреть файл

@ -42,7 +42,7 @@ func main() {
log.Info(*cell, *schemaFile)
if *schemaFile != "" {
var err error
if schema, err = planbuilder.LoadSchemaJSON(*schemaFile); err != nil {
if schema, err = planbuilder.LoadFile(*schemaFile); err != nil {
log.Fatal(err)
}
}

Просмотреть файл

@ -281,6 +281,13 @@ type Server interface {
GetSubprocessFlags() []string
}
// Schemafier is a temporary interface for supporting vschema
// reads and writes. It will eventually be merged into Server.
type Schemafier interface {
SaveVSchema(string) error
GetVSchema() (string, error)
}
// Registry for Server implementations.
var serverImpls map[string]Server = make(map[string]Server)

Просмотреть файл

@ -1,3 +1,4 @@
// TODO(sougou): The comments below look obsolete. Need to verify.
// Package test contains utilities to test topo.Server
// implementations. If you are testing your implementation, you will
// want to call CheckAll in your test method. For an example, look at

Просмотреть файл

@ -0,0 +1,55 @@
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package test
import (
"testing"
"github.com/youtube/vitess/go/vt/topo"
)
func CheckVSchema(t *testing.T, ts topo.Server) {
schemafier, ok := ts.(topo.Schemafier)
if !ok {
t.Errorf("%T is not a Schemafier", ts)
return
}
got, err := schemafier.GetVSchema()
if err != nil {
t.Error(err)
}
want := "{}"
if got != want {
t.Errorf("GetVSchema: %s, want %s", got, want)
}
err = schemafier.SaveVSchema("aa")
if err != nil {
t.Error(err)
}
got, err = schemafier.GetVSchema()
if err != nil {
t.Error(err)
}
want = "aa"
if got != want {
t.Errorf("GetVSchema: %s, want %s", got, want)
}
err = schemafier.SaveVSchema("bb")
if err != nil {
t.Error(err)
}
got, err = schemafier.GetVSchema()
if err != nil {
t.Error(err)
}
want = "bb"
if got != want {
t.Errorf("GetVSchema: %s, want %s", got, want)
}
}

Просмотреть файл

@ -84,7 +84,7 @@ func TestPlanName(t *testing.T) {
}
func TestPlan(t *testing.T) {
schema, err := LoadSchemaJSON(locateFile("schema_test.json"))
schema, err := LoadFile(locateFile("schema_test.json"))
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -5,10 +5,10 @@
package planbuilder
import (
"encoding/json"
"fmt"
"io/ioutil"
"sort"
"github.com/youtube/vitess/go/jscfg"
)
// Schema represents the denormalized version of SchemaFormal,
@ -186,13 +186,20 @@ type ColVindexFormal struct {
Name string
}
// LoadSchemaJSON loads the formal representation of a schema
// from a JSON file and returns the more usable denormalized
// representaion (Schema) for it.
func LoadSchemaJSON(filename string) (schema *Schema, err error) {
// LoadFile creates a new Schema from a JSON file.
func LoadFile(filename string) (schema *Schema, err error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("ReadFile failed: %v %v", filename, err)
}
return NewSchema(data)
}
// NewSchema creates a new Schema from a JSON byte array.
func NewSchema(data []byte) (schema *Schema, err error) {
var source SchemaFormal
if err := jscfg.ReadJson(filename, &source); err != nil {
return nil, err
if err := json.Unmarshal(data, &source); err != nil {
return nil, fmt.Errorf("Unmarshal failed: %v %s %v", source, data, err)
}
return BuildSchema(&source)
}

Просмотреть файл

@ -5,8 +5,6 @@
package planbuilder
import (
"io/ioutil"
"os"
"reflect"
"strings"
"testing"
@ -265,23 +263,16 @@ func TestShardedSchemaNotOwned(t *testing.T) {
}
func TestLoadSchemaFail(t *testing.T) {
badSchema := "{,}"
f, err := ioutil.TempFile("", "schema_test")
if err != nil {
t.Fatal(err)
}
fname := f.Name()
f.Close()
defer os.Remove(fname)
err = ioutil.WriteFile(fname, []byte(badSchema), 0644)
if err != nil {
t.Fatal(err)
}
_, err = LoadSchemaJSON(fname)
want := "ReadJson failed"
_, err := LoadFile("bogus file name")
want := "ReadFile failed"
if err == nil || !strings.HasPrefix(err.Error(), want) {
t.Errorf("LoadSchemaJSON: \n%q, should start with \n%q", err, want)
t.Errorf("LoadFile: \n%q, should start with \n%q", err, want)
}
_, err = NewSchema([]byte("{,}"))
want = "Unmarshal failed"
if err == nil || !strings.HasPrefix(err.Error(), want) {
t.Errorf("LoadFile: \n%q, should start with \n%q", err, want)
}
}

Просмотреть файл

@ -206,7 +206,7 @@ func createTestSchema(schemaJSON string) *planbuilder.Schema {
if err != nil {
panic(err)
}
schema, err := planbuilder.LoadSchemaJSON(fname)
schema, err := planbuilder.LoadFile(fname)
if err != nil {
panic(err)
}

Просмотреть файл

@ -45,3 +45,17 @@ func (s *TestServer) LockSrvShardForAction(ctx context.Context, cell, keyspace,
}
return s.Server.LockSrvShardForAction(ctx, cell, keyspace, shard, contents)
}
// TODO(sougou): Remove these two functions after they're
// migrated into topo.Server.
// SaveVSchema has to be redefined here.
// Otherwise the test type assertion fails.
func (s *TestServer) SaveVSchema(vschema string) error {
return s.Server.(topo.Schemafier).SaveVSchema(vschema)
}
// GetVSchema has to be redefined here.
// Otherwise the test type assertion fails.
func (s *TestServer) GetVSchema() (string, error) {
return s.Server.(topo.Schemafier).GetVSchema()
}

36
go/vt/zktopo/vschema.go Normal file
Просмотреть файл

@ -0,0 +1,36 @@
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package zktopo
import (
"github.com/youtube/vitess/go/zk"
"launchpad.net/gozk/zookeeper"
)
/*
This file contains the vschema management code for zktopo.Server
*/
const (
globalVSchemaPath = "/zk/global/vt/vschema"
)
// SaveVSchema saves the JSON vschema into the topo.
func (zkts *Server) SaveVSchema(vschema string) error {
_, err := zk.CreateOrUpdate(zkts.zconn, globalVSchemaPath, vschema, 0, zookeeper.WorldACL(zookeeper.PERM_ALL), true)
return err
}
// GetVSchema fetches the JSON vschema from the topo.
func (zkts *Server) GetVSchema() (string, error) {
data, _, err := zkts.zconn.Get(globalVSchemaPath)
if err != nil {
if zookeeper.IsError(err, zookeeper.ZNONODE) {
return "{}", nil
}
return "", err
}
return data, nil
}

Просмотреть файл

@ -63,3 +63,9 @@ func TestSrvShardLock(t *testing.T) {
defer ts.Close()
test.CheckSrvShardLock(t, ts)
}
func TestVSchema(t *testing.T) {
ts := NewTestServer(t, []string{"test"})
defer ts.Close()
test.CheckVSchema(t, ts)
}