-
-
Notifications
You must be signed in to change notification settings - Fork 275
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
Cluster read only #100
Cluster read only #100
Conversation
c494ae2
to
5dc3a76
Compare
} | ||
|
||
if node.ReadOnly == true { | ||
isReadOnly = isReadOnly && true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Write it just once and above if statement. And use logical OR because using AND it will not work.
isReadOnly = isReadOnly && !node.ReadOnly
} | ||
|
||
} | ||
glog.Infof("\n---------- displaying the array/checking if every value is the same---------------\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need of debugging logging anymore.
f.updateNodeCondition(host, api.NodeConditionMaster, core.ConditionFalse) | ||
} | ||
if err == nil { | ||
root = append(root, master) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename it to masterForNode
7e9144d
to
ded1f6c
Compare
} | ||
|
||
if len(getMasterForNode(insts)) != 0 { | ||
masterHostName, check := verifyMasterArray(getMasterForNode(insts)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can merge those two functions, you will always use them like this verifyMasterArray(getMasterForNode(insts))
so you can make just one function:
func determinMasterFor(inst []orc.Instace) (string, err)
|
||
} | ||
|
||
if len(getMasterForNode(insts)) != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this check
func (f *cFactory) setMasterWritable(masterHostName string, insts []orc.Instance) { | ||
master, err := getInstance(masterHostName, insts) | ||
|
||
if err == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if err != nil {
glog.Errorf("Get instance error:%s", err)
return
}
@@ -30,6 +30,9 @@ type Interface interface { | |||
|
|||
AuditRecovery(cluster string) ([]TopologyRecovery, error) | |||
AckRecovery(id int64, commnet string) error | |||
|
|||
SetHostWritable(host string, port int) error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use as parameter InstanceKey
because instance key has both host
and port
f.updateNodeCondition(masterHostName, api.NodeConditionMaster, core.ConditionFalse) | ||
} | ||
|
||
f.setMasterWritable(masterHostName, insts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this function call at line 48 after updateStatusFromOrc
call
} | ||
|
||
func (f *cFactory) setMasterWritable(masterHostName string, insts []orc.Instance) { | ||
master, err := getInstance(masterHostName, insts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can compute masterHostName
using determinMasterFor
and don't need to pass it as parameter. See see the next comments.
6e78f63
to
eebc592
Compare
if err == nil { | ||
f.updateNodeCondition(masterHostName, api.NodeConditionMaster, core.ConditionTrue) | ||
} else { | ||
f.updateNodeCondition(masterHostName, api.NodeConditionMaster, core.ConditionFalse) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there is an error then what value masterHostName
will have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else statement can be deleted or better log the error
f.updateNodeCondition(masterHostName, api.NodeConditionMaster, core.ConditionFalse) | ||
} | ||
|
||
err = f.setMasterWritable(masterHostName, insts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code should be moved in SyncOrchestratorStatus
function near to updateStatusFromOrc
call.
} | ||
|
||
func (f *cFactory) setMasterWritable(masterHostName string, insts []orc.Instance) error { | ||
master, err := getInstance(masterHostName, insts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get master here with determineMasterFor
.
Also in this function you have to make sure that only one node is writable!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure that failover works as expected, by manually testing.
Test case:
- create a cluster 2 nodes
- delete pod 0
- check node:0 -> read only and node:1 -> writable (cluster status)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test case 2:
- create cluster 3 nodes
- make node:1 comaster
- check status
a4b9f6d
to
cc95119
Compare
query = "SET GLOBAL SUPER_READ_ONLY = 1" | ||
} | ||
|
||
query = "SET GLOBAL SUPER_READ_ONLY = 1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query := "SET GLOBAL SUPER_READ_ONLY = 1"
pkg/apis/mysql/v1alpha1/types.go
Outdated
@@ -107,6 +107,8 @@ type ClusterSpec struct { | |||
// QueryLimits represents limits for a query | |||
// +optional | |||
QueryLimits *QueryLimits `json:"queryLimits,omitempty"` | |||
|
|||
ReadOnly bool `json:"readOnly,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a description here
|
||
func (f *cFactory) updateNodesReadOnlyFlagInOrc(insts []orc.Instance) error { | ||
master, err := determineMasterFor(insts) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's treat the error here, the code will be much more clearly.
master, err := determineMasterFor(insts)
if err != nil {
// if no master determined then set the cluster in read only.
for _, inst := range insts {
f.putNodeInMaintenance(inst)
f.setInstReadOnly(inst)
}
}
} else { | ||
f.updateNodeCondition(host, api.NodeConditionReadOnly, core.ConditionFalse) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to many new lines.
} | ||
|
||
master, err := determineMasterFor(insts) | ||
if err == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if err != nil {
glog.Errorf("Error acquiring master name %s", err)
}
f.updateNodeCondition(master.Key.Hostname, api.NodeConditionMaster, core.ConditionTrue)
....
"k8s.io/client-go/kubernetes/fake" | ||
"k8s.io/client-go/tools/record" | ||
"testing" | ||
"time" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the time
and testing
should be in the first group of imports, then in the second group external imports and finally the third group should be local imports.
@@ -99,6 +98,8 @@ var _ = Describe("Mysql cluster reconcilation", func() { | |||
Ω(rec.Events).Should(Receive(&event)) | |||
Expect(event).To(ContainSubstring("ReplicationStopped")) | |||
Ω(rec.Events).Should(Receive(&event)) | |||
Expect(event).To(ContainSubstring("DemoteMaster")) | |||
Ω(rec.Events).Should(Receive(&event)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's replace all Ω
with Expect
. Ω
is hard to type.
pkg/util/orchestrator/fake/client.go
Outdated
@@ -65,6 +65,38 @@ func (o *FakeOrc) AddInstance(cluster, host string, master bool, sls int64, slav | |||
o.Clusters[cluster] = []Instance{inst} | |||
} | |||
|
|||
func (o *FakeOrc) AddInstanceInTopology(cluster, host string, port int, master bool, sls int64, slaveR, upToDate bool, masterKey string, masterPort int, coMaster bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose that, lets return a pointer to newly created Instance
so you can easily modify instance so you don't need to pass that much parameters to this function.
And also you can use AddInstance
function from above.
func (o *FakeOrc) AddInstance(cluster, host string, master bool, sls int64, slaveR, upToDate bool) *Instance
By keeping the old parameters you don't have to modify old tests. The new test will lock like:
inst := orcClient.AddInstanceInTopology("asd.default", "foo122-mysql-0",
3306, false, -1, false, true)
inst.MasterKey = InstanceKey{Hostname: "foo122-mysql-5", Port: 3305}
inst.IsCoMaster = true
pkg/util/orchestrator/fake/client.go
Outdated
|
||
func (o *FakeOrc) SetHostWritable(key InstanceKey) error { | ||
|
||
var check bool = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check := false
|
||
} | ||
|
||
func (o *orchestrator) EndMaintenance(key InstanceKey, owner, reason string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't use owner
and reason
params.
13dd266
to
0b714ea
Compare
test/e2e/cluster/cluster.go
Outdated
} | ||
|
||
// tests if the cluster is in orchestrator and is properly configured | ||
func testClusterRegistrationInOrchestrator(f *framework.Framework, cluster *api.MysqlCluster, ClusterReadOnly bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use lower letter for ClusterReadOnly
param
} | ||
|
||
return nil | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line
pkg/util/orchestrator/fake/client.go
Outdated
} | ||
o.Clusters[cluster] = []Instance{inst} | ||
|
||
for _, inst1 := range o.Clusters[cluster] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to iterate over any more.
Also you can create inst
in the first place as pointer and to return the address:
inst := &Instance{
...
return inst
|
||
_, err := determineMasterFor(insts) | ||
Expect(err).ToNot(BeNil()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line
|
||
_, err := determineMasterFor(insts) | ||
Expect(err).ToNot(BeNil()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line
|
||
_, err := determineMasterFor(insts) | ||
Expect(err).To(BeNil()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line
|
||
Expect(cluster.Status.Nodes[0].GetCondition(api.NodeConditionMaster).Status).To( | ||
Equal(core.ConditionTrue)) | ||
|
||
orcClient.RemoveInstance("asd.default", cluster.GetPodHostname(0)) | ||
Ω(factory.SyncOrchestratorStatus(ctx)).Should(Succeed()) | ||
Expect(factory.SyncOrchestratorStatus(ctx)).Should(Succeed()) | ||
|
||
Expect(cluster.Status.Nodes[0].GetCondition(api.NodeConditionMaster).Status).To( | ||
Equal(core.ConditionUnknown)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line
fakeOrc "github.com/presslabs/mysql-operator/pkg/util/orchestrator/fake" | ||
tutil "github.com/presslabs/mysql-operator/pkg/util/test" | ||
core "k8s.io/api/core/v1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
external imports should be in the second group of imports.
First is go imports, second is external imports and third are the local imports(imports from project)
397e7e4
to
197e025
Compare
…use this is probably the default behavior that users of vtop want. (bitpoke#100) Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
No description provided.