Skip to content

Commit f7ef224

Browse files
author
jmccormick2001
committed
add pgo delete label command, update docs
1 parent 72b60dd commit f7ef224

File tree

8 files changed

+339
-9
lines changed

8 files changed

+339
-9
lines changed

apiserver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func main() {
9292
//here
9393
r.HandleFunc("/ingestdelete/{name}", ingestservice.DeleteIngestHandler).Methods("GET")
9494
r.HandleFunc("/label", labelservice.LabelHandler).Methods("POST")
95+
r.HandleFunc("/labeldelete", labelservice.DeleteLabelHandler).Methods("POST")
9596
r.HandleFunc("/load", loadservice.LoadHandler).Methods("POST")
9697
r.HandleFunc("/user", userservice.UserHandler).Methods("POST")
9798
r.HandleFunc("/users", userservice.CreateUserHandler).Methods("POST")

apiserver/labelservice/labelimpl.go

Lines changed: 203 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import (
3434

3535
// Label ... 2 forms ...
3636
// pgo label myucluser yourcluster --label=env=prod
37-
// pgo label myucluser yourcluster --label=env=prod --delete-label
3837
// pgo label --label=env=prod --selector=name=mycluster
3938
func Label(request *msgs.LabelRequest) msgs.LabelResponse {
4039
var err error
@@ -190,7 +189,7 @@ func updateLabels(deployment *v1beta1.Deployment, clusterName string, newLabels
190189

191190
_, err = apiserver.Clientset.ExtensionsV1beta1().Deployments(apiserver.Namespace).Patch(clusterName, types.MergePatchType, patchBytes, "")
192191
if err != nil {
193-
log.Debug("error patching deployment " + err.Error())
192+
log.Debug("error updating patching deployment " + err.Error())
194193
}
195194
return err
196195

@@ -256,3 +255,205 @@ func validateLabel(LabelCmdLabel string) (map[string]string, error) {
256255
}
257256
return labelMap, err
258257
}
258+
259+
// DeleteLabel ...
260+
// pgo delete label mycluster yourcluster --label=env=prod
261+
// pgo delete label --label=env=prod --selector=group=somegroup
262+
func DeleteLabel(request *msgs.DeleteLabelRequest) msgs.LabelResponse {
263+
var err error
264+
var labelsMap map[string]string
265+
resp := msgs.LabelResponse{}
266+
resp.Status.Code = msgs.Ok
267+
resp.Status.Msg = ""
268+
resp.Results = make([]string, 0)
269+
270+
if len(request.Args) == 0 && request.Selector == "" {
271+
resp.Status.Code = msgs.Error
272+
resp.Status.Msg = "no clusters specified"
273+
return resp
274+
}
275+
276+
labelsMap, err = validateLabel(request.LabelCmdLabel)
277+
if err != nil {
278+
resp.Status.Code = msgs.Error
279+
resp.Status.Msg = "labels not formatted correctly"
280+
return resp
281+
}
282+
283+
clusterList := crv1.PgclusterList{}
284+
if len(request.Args) > 0 && request.Args[0] == "all" {
285+
err = kubeapi.GetpgclustersBySelector(apiserver.RESTClient,
286+
&clusterList, "", apiserver.Namespace)
287+
if err != nil {
288+
log.Error("error getting list of clusters" + err.Error())
289+
resp.Status.Code = msgs.Error
290+
resp.Status.Msg = "error getting list of clusters" + err.Error()
291+
return resp
292+
}
293+
if len(clusterList.Items) == 0 {
294+
resp.Status.Code = msgs.Error
295+
resp.Status.Msg = "no clusters found"
296+
return resp
297+
}
298+
299+
} else if request.Selector != "" {
300+
err = kubeapi.GetpgclustersBySelector(apiserver.RESTClient,
301+
&clusterList, request.Selector, apiserver.Namespace)
302+
if err != nil {
303+
log.Error("error getting list of clusters" + err.Error())
304+
resp.Status.Code = msgs.Error
305+
resp.Status.Msg = "error getting list of clusters" + err.Error()
306+
return resp
307+
}
308+
if len(clusterList.Items) == 0 {
309+
resp.Status.Code = msgs.Error
310+
resp.Status.Msg = "no clusters found"
311+
return resp
312+
}
313+
} else {
314+
//each arg represents a cluster name
315+
items := make([]crv1.Pgcluster, 0)
316+
for _, cluster := range request.Args {
317+
result := crv1.Pgcluster{}
318+
_, err := kubeapi.Getpgcluster(apiserver.RESTClient,
319+
&result, cluster, apiserver.Namespace)
320+
if err != nil {
321+
resp.Status.Code = msgs.Error
322+
resp.Status.Msg = "error getting list of clusters" + err.Error()
323+
return resp
324+
}
325+
326+
items = append(items, result)
327+
}
328+
clusterList.Items = items
329+
}
330+
331+
for _, c := range clusterList.Items {
332+
resp.Results = append(resp.Results, "deleting label from "+c.Spec.Name)
333+
}
334+
335+
err = deleteLabels(clusterList.Items, request.LabelCmdLabel, labelsMap)
336+
if err != nil {
337+
resp.Status.Code = msgs.Error
338+
resp.Status.Msg = err.Error()
339+
return resp
340+
}
341+
342+
return resp
343+
344+
}
345+
346+
func deleteLabels(items []crv1.Pgcluster, LabelCmdLabel string, labelsMap map[string]string) error {
347+
var err error
348+
349+
for i := 0; i < len(items); i++ {
350+
log.Debugf("deleting label from %s", items[i].Spec.Name)
351+
err = deletePatchPgcluster(LabelCmdLabel, items[i])
352+
if err != nil {
353+
log.Error(err.Error())
354+
return err
355+
}
356+
}
357+
358+
for i := 0; i < len(items); i++ {
359+
//get deployments for this CRD
360+
selector := util.LABEL_PG_CLUSTER + "=" + items[i].Spec.Name
361+
deployments, err := kubeapi.GetDeployments(apiserver.Clientset, selector, apiserver.Namespace)
362+
if err != nil {
363+
return err
364+
}
365+
366+
for _, d := range deployments.Items {
367+
err = deleteTheLabel(&d, items[i].Spec.Name, labelsMap)
368+
if err != nil {
369+
log.Error(err.Error())
370+
return err
371+
}
372+
}
373+
374+
}
375+
return err
376+
}
377+
378+
func deletePatchPgcluster(newLabel string, oldCRD crv1.Pgcluster) error {
379+
380+
fields := strings.Split(newLabel, "=")
381+
labelKey := fields[0]
382+
//labelValue := fields[1]
383+
oldData, err := json.Marshal(oldCRD)
384+
if err != nil {
385+
return err
386+
}
387+
if oldCRD.ObjectMeta.Labels == nil {
388+
oldCRD.ObjectMeta.Labels = make(map[string]string)
389+
}
390+
delete(oldCRD.ObjectMeta.Labels, labelKey)
391+
392+
var newData, patchBytes []byte
393+
newData, err = json.Marshal(oldCRD)
394+
if err != nil {
395+
return err
396+
}
397+
patchBytes, err = jsonpatch.CreateMergePatch(oldData, newData)
398+
if err != nil {
399+
return err
400+
}
401+
402+
log.Debug(string(patchBytes))
403+
_, err6 := apiserver.RESTClient.Patch(types.MergePatchType).
404+
Namespace(apiserver.Namespace).
405+
Resource(crv1.PgclusterResourcePlural).
406+
Name(oldCRD.Spec.Name).
407+
Body(patchBytes).
408+
Do().
409+
Get()
410+
411+
return err6
412+
413+
}
414+
415+
func deleteTheLabel(deployment *v1beta1.Deployment, clusterName string, labelsMap map[string]string) error {
416+
417+
var err error
418+
419+
log.Debugf("%v are the labels to delete\n", labelsMap)
420+
421+
var patchBytes, newData, origData []byte
422+
origData, err = json.Marshal(deployment)
423+
if err != nil {
424+
return err
425+
}
426+
427+
accessor, err2 := meta.Accessor(deployment)
428+
if err2 != nil {
429+
return err2
430+
}
431+
432+
objLabels := accessor.GetLabels()
433+
if objLabels == nil {
434+
objLabels = make(map[string]string)
435+
}
436+
437+
for k, _ := range labelsMap {
438+
delete(objLabels, k)
439+
}
440+
log.Debugf("revised labels after delete are %v\n", objLabels)
441+
442+
accessor.SetLabels(objLabels)
443+
newData, err = json.Marshal(deployment)
444+
if err != nil {
445+
return err
446+
}
447+
448+
patchBytes, err = jsonpatch.CreateMergePatch(origData, newData)
449+
if err != nil {
450+
return err
451+
}
452+
453+
_, err = apiserver.Clientset.ExtensionsV1beta1().Deployments(apiserver.Namespace).Patch(deployment.Name, types.MergePatchType, patchBytes, "")
454+
if err != nil {
455+
log.Debug("error patching deployment " + err.Error())
456+
}
457+
return err
458+
459+
}

apiserver/labelservice/labelservice.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,30 @@ func LabelHandler(w http.ResponseWriter, r *http.Request) {
4949

5050
json.NewEncoder(w).Encode(resp)
5151
}
52+
53+
// DeleteLabelHandler ...
54+
func DeleteLabelHandler(w http.ResponseWriter, r *http.Request) {
55+
56+
log.Debug("labelservice.DeleteLabelHandler called")
57+
58+
var request msgs.DeleteLabelRequest
59+
_ = json.NewDecoder(r.Body).Decode(&request)
60+
61+
err := apiserver.Authn(apiserver.LABEL_PERM, w, r)
62+
if err != nil {
63+
return
64+
}
65+
66+
w.WriteHeader(http.StatusOK)
67+
w.Header().Set("Content-Type", "application/json")
68+
69+
var resp msgs.LabelResponse
70+
if request.ClientVersion != msgs.PGO_VERSION {
71+
resp = msgs.LabelResponse{}
72+
resp.Status = msgs.Status{Msg: apiserver.VERSION_MISMATCH_ERROR, Code: msgs.Error}
73+
} else {
74+
resp = DeleteLabel(&request)
75+
}
76+
77+
json.NewEncoder(w).Encode(resp)
78+
}

apiservermsgs/labelmsgs.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ type LabelRequest struct {
2828
ClientVersion string
2929
}
3030

31+
// DeleteLabelRequest ...
32+
type DeleteLabelRequest struct {
33+
Selector string
34+
Namespace string
35+
Args []string
36+
LabelCmdLabel string
37+
ClientVersion string
38+
}
39+
3140
// LabelResponse ...
3241
type LabelResponse struct {
3342
Results []string

hugo/content/getting-started/_index.adoc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,9 +1011,6 @@ $ pgo label [NAME]|all [FLAGS]
10111011
|=========================================================
10121012
|Name |Shorthand |Input |Usage
10131013
1014-
|`--delete-label` |N/A |String |
1015-
Deletes a label from specified clusters.
1016-
10171014
|`--dry-run` |N/A |N/A |
10181015
Shows the clusters that the label would be applied to, without labelling them.
10191016
@@ -1043,6 +1040,13 @@ In the first example, a label of *env=research* is applied to the cluster
10431040
*mycluster*. The second example will apply the label to any clusters that
10441041
have an existing label of *project=xray* applied or to all clusters.
10451042
1043+
===== Removing Labels
1044+
1045+
You can delete a user defined label from a cluster as follows:
1046+
....
1047+
pgo delete label mycluster --label=env=research
1048+
....
1049+
10461050
=== Creating SQL Policies
10471051
10481052
Policies are SQL files that can be applied to a single cluster, a selection

pgo/api/label.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,40 @@ func LabelClusters(httpclient *http.Client, SessionCredentials *msgs.BasicAuthCr
5959

6060
return response, err
6161
}
62+
63+
func DeleteLabel(httpclient *http.Client, SessionCredentials *msgs.BasicAuthCredentials, request *msgs.DeleteLabelRequest) (msgs.LabelResponse, error) {
64+
65+
var response msgs.LabelResponse
66+
url := SessionCredentials.APIServerURL + "/labeldelete"
67+
log.Debug("delete label called...[" + url + "]")
68+
69+
jsonValue, _ := json.Marshal(request)
70+
71+
action := "POST"
72+
req, err := http.NewRequest(action, url, bytes.NewBuffer(jsonValue))
73+
if err != nil {
74+
return response, err
75+
}
76+
req.Header.Set("Content-Type", "application/json")
77+
req.SetBasicAuth(SessionCredentials.Username, SessionCredentials.Password)
78+
79+
resp, err := httpclient.Do(req)
80+
if err != nil {
81+
return response, err
82+
}
83+
defer resp.Body.Close()
84+
85+
log.Debugf("%v\n", resp)
86+
err = StatusCheck(resp)
87+
if err != nil {
88+
return response, err
89+
}
90+
91+
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
92+
log.Printf("%v\n", resp.Body)
93+
log.Println(err)
94+
return response, err
95+
}
96+
97+
return response, err
98+
}

0 commit comments

Comments
 (0)