Skip to content

Commit 55837e1

Browse files
authored
tooling: first pass at cassandra setup-schema tool (#171)
1 parent ba64999 commit 55837e1

File tree

14 files changed

+1102
-37
lines changed

14 files changed

+1102
-37
lines changed

.travis.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,16 @@ addons:
1919

2020
before_install:
2121
- pip install --user ccm
22-
- pip install --user cqlsh==5.0.3
2322

2423
install:
2524
- go get -u github.com/Masterminds/glide
2625
- go get github.com/axw/gocov/gocov
2726
- go get github.com/mattn/goveralls
2827
- go get golang.org/x/tools/cmd/cover
29-
- ccm create test -v 2.2.8 -n 1 -s
30-
- sudo ln -sf /home/travis/.local/bin/cqlsh /usr/local/bin/cqlsh
28+
- ccm create test -v 3.9 -n 1 -s
3129

3230
script:
3331
- make cover_ci
3432

3533
after_success:
36-
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
34+
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)

Makefile

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ THRIFT_SRCS = idl/github.com/uber/cadence/cadence.thrift \
1818
PROGS = cadence
1919
TEST_ARG ?= -race -v -timeout 5m
2020
BUILD := ./build
21+
TOOLS_CMD_ROOT=./cmd/tools
2122

2223
export PATH := $(GOPATH)/bin:$(PATH)
2324

2425
THRIFT_GEN=$(GOPATH)/bin/thrift-gen
2526

26-
2727
define thriftrule
2828
THRIFT_GEN_SRC += $(THRIFT_GENDIR)/go/$1/tchan-$1.go
2929

@@ -43,23 +43,32 @@ ALL_SRC := $(shell find . -name "*.go" | grep -v -e Godeps -e vendor \
4343
-e ".*/_.*" \
4444
-e ".*/mocks.*")
4545

46+
# filter out the src files for tools
47+
TOOLS_SRC := $(shell find ./tools -name "*.go")
48+
TOOLS_SRC += $(TOOLS_CMD_ROOT)
49+
4650
# all directories with *_test.go files in them
4751
TEST_DIRS := $(sort $(dir $(filter %_test.go,$(ALL_SRC))))
4852

49-
glide:
53+
vendor/glide.updated: glide.lock glide.yaml
5054
glide install
55+
touch vendor/glide.updated
5156

5257
clean_thrift:
5358
rm -rf .gen
5459

55-
thriftc: clean_thrift glide $(THRIFT_GEN_SRC)
60+
thriftc: clean_thrift vendor/glide.updated $(THRIFT_GEN_SRC)
5661

57-
bins: thriftc
58-
go build -i -o cadence main.go
62+
cadence-cassandra-tool: vendor/glide.updated $(TOOLS_SRC)
63+
go build -i -o cadence-cassandra-tool cmd/tools/cassandra/main.go
5964

60-
bins_nothrift: glide
65+
cadence: vendor/glide.updated main.go
6166
go build -i -o cadence main.go
6267

68+
bins_nothrift: cadence-cassandra-tool cadence
69+
70+
bins: thriftc bins_nothrift
71+
6372
test: bins
6473
@rm -f test
6574
@rm -f test.log
@@ -86,3 +95,4 @@ cover_ci: cover_profile
8695

8796
clean:
8897
rm -rf cadence
98+
rm -rf cadence-cassandra-tool

cmd/tools/cassandra/main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package main
2+
3+
import (
4+
"github.com/uber/cadence/tools/cassandra"
5+
"os"
6+
)
7+
8+
func main() {
9+
cassandra.RunTool(os.Args)
10+
}

common/cassandra_helpers.go

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import (
66

77
"github.com/uber/cadence/common/logging"
88

9-
"bytes"
10-
"os/exec"
11-
129
log "github.com/Sirupsen/logrus"
1310
"github.com/gocql/gocql"
11+
"github.com/uber/cadence/tools/cassandra"
12+
"io/ioutil"
13+
"os"
1414
)
1515

1616
// NewCassandraCluster creates a cassandra cluster given comma separated list of clusterHosts
@@ -58,19 +58,39 @@ func DropCassandraKeyspace(s *gocql.Session, keyspace string) (err error) {
5858
return
5959
}
6060

61-
// LoadCassandraSchema loads the schema from the given .cql file on this keyspace using cqlsh
62-
func LoadCassandraSchema(cqlshpath string, fileName string, keyspace string) (err error) {
63-
// Using cqlsh as I couldn't find a way to execute multiple commands through gocql.Session
64-
var out bytes.Buffer
65-
var stderr bytes.Buffer
66-
cmd := exec.Command(cqlshpath, fmt.Sprintf("--keyspace=%v", keyspace), fmt.Sprintf("--file=%v", fileName))
67-
cmd.Stdout = &out
68-
cmd.Stderr = &stderr
69-
err = cmd.Run()
70-
71-
// CQLSH doesn't return non-zero for some errors
72-
if err != nil || len(stderr.String()) > 0 {
73-
err = fmt.Errorf("LoadSchema %v returned %v. STDERR: %v", cmd.Path, err, stderr.String())
61+
// LoadCassandraSchema loads the schema from the given .cql files on this keyspace
62+
func LoadCassandraSchema(dir string, fileNames []string, keyspace string) (err error) {
63+
64+
tmpFile, err := ioutil.TempFile("", "_cadence_")
65+
if err != nil {
66+
return fmt.Errorf("error creating tmp file:%v", err.Error())
67+
}
68+
defer os.Remove(tmpFile.Name())
69+
70+
for _, file := range fileNames {
71+
content, err := ioutil.ReadFile(dir + "/" + file)
72+
if err != nil {
73+
return fmt.Errorf("error reading contents of file %v:%v", file, err.Error())
74+
}
75+
tmpFile.WriteString(string(content))
76+
tmpFile.WriteString("\n")
77+
}
78+
79+
tmpFile.Close()
80+
81+
config := &cassandra.SetupSchemaConfig{
82+
BaseConfig: cassandra.BaseConfig{
83+
CassHosts: "127.0.0.1",
84+
CassKeyspace: keyspace,
85+
},
86+
SchemaFilePath: tmpFile.Name(),
87+
Overwrite: true,
88+
DisableVersioning: true,
89+
}
90+
91+
err = cassandra.SetupSchema(config)
92+
if err != nil {
93+
err = fmt.Errorf("error loading schema:%v", err.Error())
7494
}
7595
return
7696
}

common/persistence/persistenceTestBase.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -719,8 +719,7 @@ func (s *CassandraTestCluster) setupTestCluster(keySpace string, dropKeySpace bo
719719
}
720720
s.createCluster(testWorkflowClusterHosts, testDatacenter, gocql.Consistency(1), keySpace)
721721
s.createKeyspace(1, dropKeySpace)
722-
s.loadSchema("workflow_test.cql", schemaDir)
723-
s.loadSchema("visibility_test.cql", schemaDir)
722+
s.loadSchema([]string{"workflow_test.cql", "visibility_test.cql"}, schemaDir)
724723
}
725724

726725
func (s *CassandraTestCluster) tearDownTestCluster() {
@@ -757,15 +756,13 @@ func (s *CassandraTestCluster) dropKeyspace() {
757756
}
758757
}
759758

760-
func (s *CassandraTestCluster) loadSchema(fileName string, schemaDir string) {
761-
cqlshDir := "cqlsh"
759+
func (s *CassandraTestCluster) loadSchema(fileNames []string, schemaDir string) {
762760
workflowSchemaDir := "./schema/"
763-
764761
if schemaDir != "" {
765762
workflowSchemaDir = schemaDir + "/schema/"
766763
}
767764

768-
err := common.LoadCassandraSchema(cqlshDir, workflowSchemaDir+fileName, s.keyspace)
765+
err := common.LoadCassandraSchema(workflowSchemaDir, fileNames, s.keyspace)
769766
if err != nil && !strings.Contains(err.Error(), "AlreadyExists") {
770767
log.Fatal(err)
771768
}

glide.lock

Lines changed: 7 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

glide.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ import:
2222
- package: github.com/uber-go/timer
2323
subpackages:
2424
- twheel
25+
- package: github.com/urfave/cli

tools/cassandra/config.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (c) 2017 Uber Technologies, Inc.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package cassandra
22+
23+
import "fmt"
24+
25+
type (
26+
// baseConfig is the common config
27+
// for all of the tasks that work
28+
// with cassandra
29+
BaseConfig struct {
30+
CassHosts string
31+
CassKeyspace string
32+
}
33+
34+
// UpdateSchemaConfig holds the config
35+
// params for executing a UpdateSchemaTask
36+
UpdateSchemaConfig struct {
37+
BaseConfig
38+
TargetVersion int
39+
SchemaDir string
40+
IsDryRun bool
41+
}
42+
43+
// SetupSchemaConfig holds the config
44+
// params need by the SetupSchemaTask
45+
SetupSchemaConfig struct {
46+
BaseConfig
47+
SchemaFilePath string
48+
InitialVersion int
49+
Overwrite bool // overwrite previous data
50+
DisableVersioning bool // do not use schema versioning
51+
}
52+
53+
// ConfigError is an error type that
54+
// represents a problem with the config
55+
ConfigError struct {
56+
msg string
57+
}
58+
)
59+
60+
const (
61+
cliOptEndpoint = "endpoint"
62+
cliOptKeyspace = "keyspace"
63+
cliOptVersion = "version"
64+
cliOptSchemaFile = "schema-file"
65+
cliOptOverwrite = "overwrite"
66+
cliOptDisableVersioning = "disable-versioning"
67+
68+
cliFlagEndpoint = cliOptEndpoint + ", ep"
69+
cliFlagKeyspace = cliOptKeyspace + ", k"
70+
cliFlagVersion = cliOptVersion + ", v"
71+
cliFlagSchemaFile = cliOptSchemaFile + ", f"
72+
cliFlagOverwrite = cliOptOverwrite + ", o"
73+
cliFlagDisableVersioning = cliOptDisableVersioning + ", d"
74+
)
75+
76+
func newConfigError(msg string) error {
77+
return &ConfigError{msg: msg}
78+
}
79+
80+
func (e *ConfigError) Error() string {
81+
return fmt.Sprintf("Config Error:%v", e.msg)
82+
}

0 commit comments

Comments
 (0)