Skip to content

Commit 436f02b

Browse files
author
jmccormick2001
committed
first cut at manual failover command, not completed yet, only part 1
1 parent 4a0a84e commit 436f02b

File tree

16 files changed

+596
-4
lines changed

16 files changed

+596
-4
lines changed

apis/cr/v1/task.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
const PgtaskResourcePlural = "pgtasks"
2424

2525
const PgtaskDeleteData = "delete-data"
26+
const PgtaskFailover = "failover"
2627

2728
// PgtaskSpec ...
2829
type PgtaskSpec struct {

apiserver.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
log "github.com/Sirupsen/logrus"
2222
"github.com/crunchydata/postgres-operator/apiserver/backupservice"
2323
"github.com/crunchydata/postgres-operator/apiserver/clusterservice"
24+
"github.com/crunchydata/postgres-operator/apiserver/failoverservice"
2425
"github.com/crunchydata/postgres-operator/apiserver/ingestservice"
2526
"github.com/crunchydata/postgres-operator/apiserver/labelservice"
2627
"github.com/crunchydata/postgres-operator/apiserver/loadservice"
@@ -86,6 +87,7 @@ func main() {
8687
r.HandleFunc("/clusters/scale/{name}", clusterservice.ScaleClusterHandler)
8788
r.HandleFunc("/backups/{name}", backupservice.ShowBackupHandler).Methods("GET", "DELETE")
8889
r.HandleFunc("/backups", backupservice.CreateBackupHandler).Methods("POST")
90+
r.HandleFunc("/failover", failoverservice.CreateFailoverHandler).Methods("POST")
8991

9092
caCert, err := ioutil.ReadFile(serverCert)
9193
if err != nil {
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package failoverservice
2+
3+
/*
4+
Copyright 2017-2018 Crunchy Data Solutions, Inc.
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
import (
19+
"errors"
20+
log "github.com/Sirupsen/logrus"
21+
crv1 "github.com/crunchydata/postgres-operator/apis/cr/v1"
22+
"github.com/crunchydata/postgres-operator/apiserver"
23+
msgs "github.com/crunchydata/postgres-operator/apiservermsgs"
24+
"k8s.io/api/extensions/v1beta1"
25+
kerrors "k8s.io/apimachinery/pkg/api/errors"
26+
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
//"k8s.io/apimachinery/pkg/labels"
28+
)
29+
30+
// CreateFailover ...
31+
// pgo failover mycluster
32+
// pgo failover all
33+
// pgo failover --selector=name=mycluster
34+
func CreateFailover(request *msgs.CreateFailoverRequest) msgs.CreateFailoverResponse {
35+
var err error
36+
resp := msgs.CreateFailoverResponse{}
37+
resp.Status.Code = msgs.Ok
38+
resp.Status.Msg = ""
39+
resp.Results = make([]string, 0)
40+
41+
if request.Target != "" {
42+
_, err = validateDeploymentName(request.Target)
43+
if err != nil {
44+
resp.Status.Code = msgs.Error
45+
resp.Status.Msg = err.Error()
46+
return resp
47+
}
48+
}
49+
50+
//get the clusters list
51+
//var cluster *crv1.Pgcluster
52+
_, err = validateClusterName(request.ClusterName)
53+
if err != nil {
54+
resp.Status.Code = msgs.Error
55+
resp.Status.Msg = err.Error()
56+
return resp
57+
}
58+
59+
log.Debug("create failover called for " + request.ClusterName)
60+
61+
// Create a pgtask
62+
spec := crv1.PgtaskSpec{}
63+
spec.Name = request.ClusterName + "-failover"
64+
spec.TaskType = crv1.PgtaskFailover
65+
spec.Parameters = request.ClusterName
66+
labels := make(map[string]string)
67+
labels["target"] = request.Target
68+
69+
newInstance := &crv1.Pgtask{
70+
ObjectMeta: meta_v1.ObjectMeta{
71+
Name: spec.Name,
72+
Labels: labels,
73+
},
74+
Spec: spec,
75+
}
76+
77+
result := crv1.Pgtask{}
78+
79+
err = apiserver.RESTClient.Post().
80+
Resource(crv1.PgtaskResourcePlural).
81+
Namespace(apiserver.Namespace).
82+
Body(newInstance).
83+
Do().Into(&result)
84+
if err != nil {
85+
log.Error(err.Error())
86+
resp.Status.Code = msgs.Error
87+
resp.Status.Msg = err.Error()
88+
return resp
89+
}
90+
91+
resp.Results = append(resp.Results, "created Pgtask (failover) for cluster "+request.ClusterName)
92+
93+
return resp
94+
}
95+
96+
// QueryFailover ...
97+
// pgo failover mycluster --query
98+
func QueryFailover(request *msgs.CreateFailoverRequest) msgs.CreateFailoverResponse {
99+
var err error
100+
resp := msgs.CreateFailoverResponse{}
101+
resp.Status.Code = msgs.Ok
102+
resp.Status.Msg = ""
103+
resp.Results = make([]string, 0)
104+
resp.Targets = make([]string, 0)
105+
106+
//var deployment *v1beta1.Deployment
107+
108+
//get the clusters list
109+
//var cluster *crv1.Pgcluster
110+
_, err = validateClusterName(request.ClusterName)
111+
if err != nil {
112+
resp.Status.Code = msgs.Error
113+
resp.Status.Msg = err.Error()
114+
return resp
115+
}
116+
117+
log.Debug("query failover called for " + request.ClusterName)
118+
119+
//get failover targets for this cluster
120+
//deployments with --selector=replica=true,pg-cluster=ClusterName
121+
122+
lo := meta_v1.ListOptions{LabelSelector: "replica=true,pg-cluster=" + request.ClusterName}
123+
deployments, err := apiserver.Clientset.ExtensionsV1beta1().Deployments(apiserver.Namespace).List(lo)
124+
if kerrors.IsNotFound(err) {
125+
log.Debug("no replicas found ")
126+
resp.Status.Msg = "no replicas found for " + request.ClusterName
127+
return resp
128+
} else if err != nil {
129+
log.Error("error getting deployments " + err.Error())
130+
resp.Status.Code = msgs.Error
131+
resp.Status.Msg = err.Error()
132+
return resp
133+
}
134+
135+
log.Debugf("deps len %d\n", len(deployments.Items))
136+
for _, dep := range deployments.Items {
137+
log.Debug("found " + dep.Name)
138+
resp.Targets = append(resp.Targets, dep.Name)
139+
}
140+
141+
//resp.Results = append(resp.Results, "")
142+
143+
return resp
144+
}
145+
146+
func validateClusterName(clusterName string) (*crv1.Pgcluster, error) {
147+
//get the clusters list
148+
cluster := crv1.Pgcluster{}
149+
err := apiserver.RESTClient.Get().
150+
Resource(crv1.PgclusterResourcePlural).
151+
Namespace(apiserver.Namespace).
152+
Name(clusterName).
153+
Do().
154+
Into(&cluster)
155+
if kerrors.IsNotFound(err) {
156+
log.Debug("no clusters found")
157+
return &cluster, errors.New("no cluster found named " + clusterName)
158+
} else if err != nil {
159+
log.Error("error validating cluster name" + err.Error())
160+
return &cluster, err
161+
}
162+
return &cluster, err
163+
}
164+
165+
func validateDeploymentName(deployName string) (*v1beta1.Deployment, error) {
166+
167+
deployment, err := apiserver.Clientset.ExtensionsV1beta1().Deployments(apiserver.Namespace).Get(deployName, meta_v1.GetOptions{})
168+
if kerrors.IsNotFound(err) {
169+
log.Debug("no deployment found with that target name")
170+
return deployment, errors.New("no target found named " + deployName)
171+
} else if err != nil {
172+
log.Error("error getting deployment" + err.Error())
173+
return deployment, err
174+
}
175+
176+
return deployment, err
177+
178+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package failoverservice
2+
3+
/*
4+
Copyright 2017-2018 Crunchy Data Solutions, Inc.
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
import (
19+
"encoding/json"
20+
log "github.com/Sirupsen/logrus"
21+
"github.com/crunchydata/postgres-operator/apiserver"
22+
msgs "github.com/crunchydata/postgres-operator/apiservermsgs"
23+
"net/http"
24+
)
25+
26+
// CreateFailoverHandler ...
27+
// pgo failover mycluster
28+
func CreateFailoverHandler(w http.ResponseWriter, r *http.Request) {
29+
var err error
30+
31+
log.Debug("failoverservice.CreateFailoverHandler called")
32+
33+
var request msgs.CreateFailoverRequest
34+
_ = json.NewDecoder(r.Body).Decode(&request)
35+
36+
err = apiserver.Authn(apiserver.CREATE_FAILOVER_PERM, w, r)
37+
if err != nil {
38+
return
39+
}
40+
41+
w.WriteHeader(http.StatusOK)
42+
w.Header().Set("Content-Type", "application/json")
43+
44+
var resp msgs.CreateFailoverResponse
45+
if request.Query {
46+
resp = QueryFailover(&request)
47+
} else {
48+
resp = CreateFailover(&request)
49+
}
50+
51+
json.NewEncoder(w).Encode(resp)
52+
}

apiserver/perms.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const VERSION_PERM = "Version"
4646
const CREATE_INGEST_PERM = "CreateIngest"
4747
const SHOW_INGEST_PERM = "ShowIngest"
4848
const DELETE_INGEST_PERM = "DeleteIngest"
49+
const CREATE_FAILOVER_PERM = "CreateFailover"
4950

5051
var RoleMap map[string]map[string]string
5152
var PermMap map[string]string
@@ -79,6 +80,7 @@ func init() {
7980
PermMap[CREATE_INGEST_PERM] = "yes"
8081
PermMap[SHOW_INGEST_PERM] = "yes"
8182
PermMap[DELETE_INGEST_PERM] = "yes"
83+
PermMap[CREATE_FAILOVER_PERM] = "yes"
8284
log.Infof("loading PermMap with %d Permissions\n", len(PermMap))
8385

8486
readRoles()

apiservermsgs/failovermsgs.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package apiservermsgs
2+
3+
/*
4+
Copyright 2017-2018 Crunchy Data Solutions, Inc.
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
import ()
19+
20+
// CreateFailoverResponse ...
21+
type CreateFailoverResponse struct {
22+
Results []string
23+
Targets []string
24+
Status
25+
}
26+
27+
// CreateFailoverRequest ...
28+
type CreateFailoverRequest struct {
29+
ClusterName string
30+
Target string
31+
Query bool
32+
}

bin/remove-all.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
# Copyright 2017-2018 Crunchy Data Solutions, Inc.
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
kubectl delete svc --selector=pg-cluster
17+
kubectl delete secret --selector=pg-database
18+
kubectl delete pvc --selector=pgremove
19+
kubectl delete crd pgbackups.cr.client-go.k8s.io pgclusters.cr.client-go.k8s.io pgingests.cr.client-go.k8s.io pgpolicies.cr.client-go.k8s.io pgreplicas.cr.client-go.k8s.io
20+
kubectl delete crd pgtasks.cr.client-go.k8s.io pgupgrades.cr.client-go.k8s.io

conf/apiserver/pgo.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Cluster:
22
CCPImagePrefix: crunchydata
3-
CCPImageTag: centos7-10.3-1.8.2
3+
CCPImageTag: centos7-10.3-1.8.1
44
Port: 5432
55
User: testuser
66
Database: userdb

conf/apiserver/pgorole

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
pgoadmin: ShowCluster, CreateCluster, TestCluster, ShowBackup, DeleteBackup, CreateBackup, Label, Load, CreatePolicy, DeletePolicy, ShowPolicy, ApplyPolicy, ShowPVC, CreateUpgrade, ShowUpgrade, DeleteUpgrade, CreateUser, DeleteUser, User, Version, CreateIngest, ShowIngest, DeleteIngest
1+
pgoadmin: ShowCluster, CreateCluster, TestCluster, ShowBackup, DeleteBackup, CreateBackup, Label, Load, CreatePolicy, DeletePolicy, ShowPolicy, ApplyPolicy, ShowPVC, CreateUpgrade, ShowUpgrade, DeleteUpgrade, CreateUser, DeleteUser, User, Version, CreateIngest, ShowIngest, DeleteIngest, CreateFailover
22

33
pgoreader: ShowCluster, TestCluster, ShowBackup, ShowPolicy, ShowPVC, ShowUpgrade, Version

controller/taskcontroller.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"k8s.io/client-go/tools/cache"
2727

2828
crv1 "github.com/crunchydata/postgres-operator/apis/cr/v1"
29+
clusteroperator "github.com/crunchydata/postgres-operator/operator/cluster"
2930
taskoperator "github.com/crunchydata/postgres-operator/operator/task"
3031
)
3132

@@ -124,6 +125,12 @@ func (c *PgtaskController) onAdd(obj interface{}) {
124125

125126
//process the incoming task
126127
switch task.Spec.TaskType {
128+
case crv1.PgtaskFailover:
129+
log.Info("failover task added")
130+
log.Info("cluster name is " + task.Spec.Parameters)
131+
log.Info("dbname is " + task.Spec.Name)
132+
clusteroperator.FailoverBase(task.ObjectMeta.Namespace, c.PgtaskClientset, c.PgtaskClient, task)
133+
127134
case crv1.PgtaskDeleteData:
128135
log.Info("delete data task added")
129136
log.Info("pvc is " + task.Spec.Parameters)
@@ -145,7 +152,7 @@ func (c *PgtaskController) onAdd(obj interface{}) {
145152
if err != nil {
146153
log.Errorf("ERROR deleting pgtask status: %s %v\n", task.ObjectMeta.Name, err)
147154
} else {
148-
log.Errorf("UPDATED deleted pgtask %s\n", task.ObjectMeta.Name)
155+
log.Errorf("deleted pgtask %s\n", task.ObjectMeta.Name)
149156
}
150157

151158
}

0 commit comments

Comments
 (0)