6ec3f085508364e0649df4199576290160e8f3bd
[nonrtric/plt/sme.git] / servicemanager / internal / kongclear / kongclear.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2024: OpenInfra Foundation Europe
6 //   %%
7 //   Licensed under the Apache License, Version 2.0 (the "License");
8 //   you may not use this file except in compliance with the License.
9 //   You may obtain a copy of the License at
10 //
11 //        http://www.apache.org/licenses/LICENSE-2.0
12 //
13 //   Unless required by applicable law or agreed to in writing, software
14 //   distributed under the License is distributed on an "AS IS" BASIS,
15 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 //   See the License for the specific language governing permissions and
17 //   limitations under the License.
18 //   ========================LICENSE_END===================================
19 //
20
21 package kongclear
22
23 import (
24         "encoding/json"
25         "fmt"
26         "net/http"
27         "strings"
28
29         resty "github.com/go-resty/resty/v2"
30         log "github.com/sirupsen/logrus"
31 )
32
33 // Service represents the structure for Kong service creation
34 type KongService struct {
35         ID   string   `json:"id"`
36         Name string   `json:"name"`
37         URL  string   `json:"url"`
38         Tags []string `json:"tags"`
39 }
40
41 type KongServiceResponse struct {
42         ID string `json:"id"`
43 }
44
45 type ServiceResponse struct {
46         Data []KongService `json:"data"`
47 }
48
49 type KongRoute struct {
50         ID        string   `json:"id"`
51         Name      string   `json:"name"`
52         Paths     []string `json:"paths"`
53         Service   Service  `json:"service"`
54         StripPath bool     `json:"strip_path"`
55         Tags      []string `json:"tags"`
56 }
57
58 type RouteResponse struct {
59         Data []KongRoute `json:"data"`
60 }
61
62 type Service struct {
63         ID string `json:"id"`
64 }
65
66 func KongClear(myEnv map[string]string, myPorts map[string]int) error {
67         log.Info("delete only ServiceManager Kong routes and services")
68
69         kongAdminApiUrl := fmt.Sprintf("%s://%s:%d/", myEnv["KONG_PROTOCOL"], myEnv["KONG_IPV4"], myPorts["KONG_CONTROL_PLANE_PORT"])
70
71         err := deleteRoutes(kongAdminApiUrl)
72         if err != nil {
73                 log.Fatalf("error deleting routes %v", err)
74                 return err
75         }
76
77         err = deleteServices(kongAdminApiUrl)
78         if err != nil {
79                 log.Fatalf("error deleting services %v", err)
80                 return err
81         }
82
83         log.Info("finished deleting only ServiceManger Kong routes and services")
84         return err
85 }
86
87 func deleteRoutes(kongAdminApiUrl string) error {
88         routes, err := listRoutes(kongAdminApiUrl)
89         if err != nil {
90                 return err
91         }
92
93         for _, route := range routes {
94                 if areServiceManagerTags(route.Tags) {
95                         if err := deleteRoute(kongAdminApiUrl, route.ID); err != nil {
96                                 return err
97                         }
98                 }
99         }
100
101         return nil
102 }
103
104 func deleteServices(kongAdminApiUrl string) error {
105         services, err := listServices(kongAdminApiUrl)
106         if err != nil {
107                 return err
108         }
109
110         for _, service := range services {
111                 if areServiceManagerTags(service.Tags) {
112                         if err := deleteService(kongAdminApiUrl, service.ID); err != nil {
113                                 return err
114                         }
115                 }
116         }
117
118         return nil
119 }
120
121 func listRoutes(kongAdminApiUrl string) ([]KongRoute, error) {
122         client := resty.New()
123         resp, err := client.R().
124                 Get(kongAdminApiUrl + "routes")
125
126         if err != nil {
127                 return nil, err
128         }
129
130         if resp.StatusCode() != http.StatusOK {
131                 err := fmt.Errorf("failed to list routes, status code %d", resp.StatusCode())
132                 return nil, err
133         }
134
135         var routeResponse RouteResponse
136         err = json.Unmarshal(resp.Body(), &routeResponse)
137         if err != nil {
138                 return nil, err
139         }
140
141         log.Infof("kong routes %v", routeResponse.Data)
142         return routeResponse.Data, nil
143 }
144
145 func listServices(kongAdminApiUrl string) ([]KongService, error) {
146         client := resty.New()
147         resp, err := client.R().Get(kongAdminApiUrl + "services")
148
149         if err != nil {
150                 return nil, err
151         }
152
153         if resp.StatusCode() != http.StatusOK {
154                 err := fmt.Errorf("failed to list services, status code %d", resp.StatusCode())
155                 return nil, err
156         }
157
158         var serviceResponse ServiceResponse
159         err = json.Unmarshal(resp.Body(), &serviceResponse)
160         if err != nil {
161                 return nil, err
162         }
163
164         log.Infof("kong services %v", serviceResponse.Data)
165         return serviceResponse.Data, nil
166 }
167
168 func areServiceManagerTags(tags []string) bool {
169         tagMap := make(map[string]string)
170
171         for _, tag := range tags {
172                 log.Debugf("found tag %s", tag)
173                 tagSlice := strings.Split(tag, ":")
174                 log.Debugf("tag slice %v", tagSlice)
175                 if (len(tagSlice) > 0) && (tagSlice[0] != "") {
176                         if (len(tagSlice) > 1) {
177                                 tagMap[tagSlice[0]] = tagSlice[1]
178                         } else {
179                                 tagMap[tagSlice[0]] = ""
180                         }
181                 }
182         }
183
184         if tagMap["apfId"] == "" {
185                 log.Debug("did NOT find apfId")
186                 return false
187         }
188         log.Debugf("found valid apfId %s", tagMap["apfId"])
189
190         if tagMap["aefId"] == "" {
191                 log.Debug("did NOT find aefId")
192                 return false
193         }
194         log.Debugf("found valid aefId %s", tagMap["aefId"])
195
196         if tagMap["apiId"] == "" {
197                 log.Debug("did NOT find apiId")
198                 return false
199         }
200         log.Debugf("found valid apiId %s", tagMap["apiId"])
201
202         return true
203 }
204
205 func deleteRoute(kongAdminApiUrl string, routeID string) error {
206         log.Infof("delete kong route id %s", routeID)
207         client := resty.New()
208         resp, err := client.R().Delete(kongAdminApiUrl + "routes/" + routeID)
209
210         if err != nil {
211                 return err
212         }
213
214         if resp.StatusCode() != http.StatusNoContent {
215                 err := fmt.Errorf("failed to delete route %s, status code %d", routeID, resp.StatusCode())
216                 return err
217         }
218
219         return nil
220 }
221
222 func deleteService(kongAdminApiUrl string, serviceID string) error {
223         log.Infof("delete kong service id %s", serviceID)
224         client := resty.New()
225         resp, err := client.R().Delete(kongAdminApiUrl + "services/" + serviceID)
226
227         if err != nil {
228                 return err
229         }
230
231         if resp.StatusCode() != http.StatusNoContent {
232                 err := fmt.Errorf("failed to delete service %s, status code %d", serviceID, resp.StatusCode())
233                 return err
234         }
235
236         return nil
237 }