Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix sidecar configuration #251

Merged
merged 2 commits into from
Mar 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ hack/docker/mysql-operator/mysql-operator

# ignore vscode
.vscode

# goland
.idea
4 changes: 2 additions & 2 deletions pkg/sidecar/appclone.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func RunCloneCommand(cfg *Config) error {
}
} else {
// clonging from prior node
if cfg.ServerID > 100 {
sourceHost := cfg.FQDNForServer(cfg.ServerID - 1)
if cfg.ServerID() > 100 {
sourceHost := cfg.FQDNForServer(cfg.ServerID() - 1)
err := cloneFromSource(cfg, sourceHost)
if err != nil {
return fmt.Errorf("failed to clone from %s, err: %s", sourceHost, err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/sidecar/appconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ func RunConfigCommand(cfg *Config) error {
}

uPass := pkgutil.RandomString(rStrLen)
reportHost := cfg.FQDNForServer(cfg.ServerID)
reportHost := cfg.FQDNForServer(cfg.ServerID())

var identityCFG, utilityCFG, clientCFG *ini.File

// mysql server identity configs
if identityCFG, err = getIdentityConfigs(cfg.ServerID, reportHost); err != nil {
if identityCFG, err = getIdentityConfigs(cfg.ServerID(), reportHost); err != nil {
return fmt.Errorf("failed to get dynamic configs: %s", err)
}
if err = identityCFG.SaveTo(path.Join(confDPath, "10-identity.cnf")); err != nil {
Expand Down
32 changes: 25 additions & 7 deletions pkg/sidecar/apphelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ func RunSidecarCommand(cfg *Config, stop <-chan struct{}) error {
func configureOrchestratorUser(cfg *Config) error {
query := `
SET @@SESSION.SQL_LOG_BIN = 0;
GRANT SUPER, PROCESS, REPLICATION SLAVE, REPLICATION CLIENT, RELOAD ON *.* TO ?@'%%' IDENTIFIED BY ?;

CREATE USER IF NOT EXISTS ?@'%%';
ALTER USER ?@'%%' IDENTIFIED BY ?;

GRANT SUPER, PROCESS, REPLICATION SLAVE, REPLICATION CLIENT, RELOAD ON *.* TO ?@'%%';
GRANT SELECT ON %s.* TO ?@'%%';
GRANT SELECT ON mysql.slave_master_info TO ?@'%%';
`
Expand All @@ -101,8 +105,9 @@ func configureOrchestratorUser(cfg *Config) error {
// https://github.com/golang/go/issues/18478
query = fmt.Sprintf(query, toolsDbName)

if err := runQuery(cfg, query, cfg.OrchestratorUser, cfg.OrchestratorPassword,
cfg.OrchestratorUser, cfg.OrchestratorPassword); err != nil {
user := cfg.OrchestratorUser
pass := cfg.OrchestratorPassword
if err := runQuery(cfg, query, user, user, pass, user, user, user); err != nil {
return fmt.Errorf("failed to configure orchestrator (user/pass/access), err: %s", err)
}

Expand All @@ -112,9 +117,15 @@ func configureOrchestratorUser(cfg *Config) error {
func configureReplicationUser(cfg *Config) error {
query := `
SET @@SESSION.SQL_LOG_BIN = 0;
GRANT SELECT, PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO ?@'%' IDENTIFIED BY ?;

CREATE USER IF NOT EXISTS ?@'%';
ALTER USER ?@'%' IDENTIFIED BY ?;

GRANT SELECT, PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO ?@'%';
`
if err := runQuery(cfg, query, cfg.ReplicationUser, cfg.ReplicationPassword); err != nil {
user := cfg.ReplicationUser
pass := cfg.ReplicationPassword
if err := runQuery(cfg, query, user, user, pass, user); err != nil {
return fmt.Errorf("failed to configure replication user: %s", err)
}

Expand All @@ -124,9 +135,16 @@ func configureReplicationUser(cfg *Config) error {
func configureExporterUser(cfg *Config) error {
query := `
SET @@SESSION.SQL_LOG_BIN = 0;
GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO ?@'127.0.0.1' IDENTIFIED BY ? WITH MAX_USER_CONNECTIONS 3;

CREATE USER IF NOT EXISTS ?@'localhost';
ALTER USER ?@'localhost' IDENTIFIED BY ? WITH MAX_USER_CONNECTIONS 3;

GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO ?@'localhost';
`
if err := runQuery(cfg, query, cfg.MetricsUser, cfg.MetricsPassword); err != nil {

user := cfg.MetricsUser
pass := cfg.MetricsPassword
if err := runQuery(cfg, query, user, user, pass, user); err != nil {
return fmt.Errorf("failed to metrics exporter user: %s", err)
}

Expand Down
43 changes: 22 additions & 21 deletions pkg/sidecar/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ type Config struct {
// ServiceName is the name of the headless service
ServiceName string

// ServerID represents the MySQL server id
ServerID int

// InitBucketURL represents the init bucket to initialize mysql
InitBucketURL string

Expand All @@ -65,14 +62,11 @@ type Config struct {
BackupUser string
BackupPassword string

// MysqlDSN represents the connection string to connect to MySQL
MysqlDSN string

// replication user and password
ReplicationUser string
ReplicationPassword string

// metrcis exporter user and password
// metrics exporter user and password
MetricsUser string
MetricsPassword string

Expand All @@ -84,7 +78,7 @@ type Config struct {
// FQDNForServer returns the pod hostname for given MySQL server id
func (cfg *Config) FQDNForServer(id int) string {
base := mysqlcluster.GetNameForResource(mysqlcluster.StatefulSet, cfg.ClusterName)
return fmt.Sprintf("%s-%d.%s.%s", base, id-100, cfg.ServiceName, cfg.Namespace)
return fmt.Sprintf("%s-%d.%s.%s", base, id-MysqlServerIDOffset, cfg.ServiceName, cfg.Namespace)
}

func (cfg *Config) newOrcClient() orc.Interface {
Expand All @@ -110,20 +104,36 @@ func (cfg *Config) MasterFQDN() string {
}

log.V(-1).Info("failed to obtain master from orchestrator, go for default master",
"master", cfg.FQDNForServer(100))
return cfg.FQDNForServer(100)
"master", cfg.FQDNForServer(MysqlServerIDOffset))
return cfg.FQDNForServer(MysqlServerIDOffset)

}

// NodeRole returns the role of the current node
func (cfg *Config) NodeRole() NodeRole {
if cfg.Hostname == cfg.MasterFQDN() {
if cfg.FQDNForServer(cfg.ServerID()) == cfg.MasterFQDN() {
return MasterNode
}

return SlaveNode
}

// ServerID returns the MySQL server id
func (cfg *Config) ServerID() int {
ordinal := getOrdinalFromHostname(cfg.Hostname)
return ordinal + MysqlServerIDOffset
}

// MysqlDSN returns the connection string to MySQL server
func (cfg *Config) MysqlDSN() string {
var dsn string
var err error
if dsn, err = getMySQLConnectionString(); err != nil {
log.Info("failed to get mysql DSN string", "error", err)
}
return dsn
}

// NewConfig returns a pointer to Config configured from environment variables
func NewConfig() *Config {
cfg := &Config{
Expand All @@ -148,22 +158,13 @@ func NewConfig() *Config {
OrchestratorPassword: getEnvValue("MYSQL_ORC_TOPOLOGY_PASSWORD"),
}

// get server id
ordinal := getOrdinalFromHostname(cfg.Hostname)
cfg.ServerID = ordinal + 100

var err error
if cfg.MysqlDSN, err = getMySQLConnectionString(); err != nil {
log.Error(err, "get mysql dsn")
}

return cfg
}

func getEnvValue(key string) string {
value := os.Getenv(key)
if len(value) == 0 {
log.Info("envirorment is not set", "key", key)
log.Info("environment is not set", "key", key)
}

return value
Expand Down
57 changes: 57 additions & 0 deletions pkg/sidecar/configs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2019 Pressinfra SRL

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package sidecar

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Test sidecar configs", func() {
var (
cfg *Config
)

BeforeEach(func() {
cfg = &Config{
Hostname: "cluster-mysql-0",
ClusterName: "cluster",
Namespace: "default",
ServiceName: "cluster-mysql-nodes",
BackupUser: "backup-user",
BackupPassword: "backup-password",
}
})

It("should fill the server id", func() {
Expect(cfg.ServerID()).To(Equal(MysqlServerIDOffset))

cfg.Hostname = "cluster-mysql-3"
Expect(cfg.ServerID()).To(Equal(MysqlServerIDOffset + 3))
})

It("should get the default master", func() {
Expect(cfg.MasterFQDN()).To(Equal("cluster-mysql-0.cluster-mysql-nodes.default"))
})

It("should determine the node role", func() {
Expect(cfg.NodeRole()).To(Equal(MasterNode))

cfg.Hostname = "cluster-mysql-2"
Expect(cfg.NodeRole()).To(Equal(SlaveNode))
})
})
3 changes: 3 additions & 0 deletions pkg/sidecar/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import (
)

var (
// MysqlServerIDOffset represents the offset with which all server ids are shifted from 0
MysqlServerIDOffset = 100

// MysqlPort represents port on which mysql works
mysqlPort = strconv.Itoa(constants.MysqlPort)

Expand Down
33 changes: 33 additions & 0 deletions pkg/sidecar/sidecar_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Copyright 2019 Pressinfra SRL

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package sidecar

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

logf "github.com/presslabs/controller-util/log"
)

func TestSidecarApp(t *testing.T) {
logf.SetLogger(logf.ZapLoggerTo(GinkgoWriter, true))

RegisterFailHandler(Fail)
RunSpecs(t, "Sidecar App Suite")
}
11 changes: 8 additions & 3 deletions pkg/sidecar/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,22 @@ var log = logf.Log.WithName("sidecar")

// runQuery executes a query
func runQuery(cfg *Config, q string, args ...interface{}) error {
if len(cfg.MysqlDSN) == 0 {
if len(cfg.MysqlDSN()) == -1 {
log.Info("could not get mysql connection DSN")
return fmt.Errorf("no DSN specified")
}

db, err := sql.Open("mysql", cfg.MysqlDSN)
db, err := sql.Open("mysql", cfg.MysqlDSN())
if err != nil {
return err
}
defer func() {
if cErr := db.Close(); cErr != nil {
log.Error(cErr, "failed closing the database connection")
}
}()

log.V(4).Info("running query", "query", q, "args", args)
log.V(1).Info("running query", "query", q, "args", args)
if _, err := db.Exec(q, args...); err != nil {
return err
}
Expand Down