github.com/stakater/IngressMonitorController@v1.0.103/pkg/monitors/gcloud/gcloud-monitor.go (about) 1 package gcloud 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "net/url" 8 "strconv" 9 10 monitoring "cloud.google.com/go/monitoring/apiv3" 11 "google.golang.org/api/iterator" 12 "google.golang.org/api/option" 13 monitoredres "google.golang.org/genproto/googleapis/api/monitoredres" 14 monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3" 15 16 "github.com/stakater/IngressMonitorController/pkg/config" 17 "github.com/stakater/IngressMonitorController/pkg/models" 18 ) 19 20 const ( 21 ProjectIDAnnotation = "gcloud.monitor.stakater.com/project-id" 22 ) 23 24 type MonitorService struct { 25 client *monitoring.UptimeCheckClient 26 projectID string 27 ctx context.Context 28 } 29 30 func (service *MonitorService) Setup(provider config.Provider) { 31 service.ctx = context.Background() 32 33 client, err := monitoring.NewUptimeCheckClient(service.ctx, option.WithCredentialsJSON([]byte(provider.ApiKey))) 34 35 if err != nil { 36 log.Println("Error Seting Up Monitor Service: ", err.Error()) 37 } else { 38 service.client = client 39 } 40 41 service.projectID = provider.GcloudConfig.ProjectID 42 } 43 44 func (service *MonitorService) GetByName(name string) (monitor *models.Monitor, err error) { 45 uptimeCheckConfigsIterator := service.client.ListUptimeCheckConfigs(service.ctx, &monitoringpb.ListUptimeCheckConfigsRequest{ 46 Parent: "projects/" + service.projectID, 47 }) 48 49 for { 50 uptimeCheckConfig, err := uptimeCheckConfigsIterator.Next() 51 if err == iterator.Done { 52 break 53 } 54 if err != nil { 55 return nil, fmt.Errorf("Error Locating Monitor: %s", err.Error()) 56 } 57 if uptimeCheckConfig.DisplayName == name { 58 localMonitor := transformToMonitor(uptimeCheckConfig) 59 return &localMonitor, nil 60 } 61 } 62 63 return nil, fmt.Errorf("Unable to locate monitor with name %v", name) 64 } 65 66 func (service *MonitorService) GetAll() (monitors []models.Monitor) { 67 uptimeCheckConfigsIterator := service.client.ListUptimeCheckConfigs(service.ctx, &monitoringpb.ListUptimeCheckConfigsRequest{ 68 Parent: "projects/" + service.projectID, 69 }) 70 71 monitors = []models.Monitor{} 72 for { 73 uptimeCheckConfig, err := uptimeCheckConfigsIterator.Next() 74 if err == iterator.Done { 75 break 76 } 77 if err != nil { 78 log.Println("Error received while listing checks: ", err.Error()) 79 return nil 80 } 81 monitors = append(monitors, transformToMonitor(uptimeCheckConfig)) 82 } 83 84 return monitors 85 } 86 87 func (service *MonitorService) Add(monitor models.Monitor) { 88 url, err := url.Parse(monitor.URL) 89 if err != nil { 90 log.Println("Error Adding Monitor: ", err.Error()) 91 return 92 } 93 94 portString := url.Port() 95 var port int 96 if portString == "" { 97 if url.Scheme == "http" { 98 port = 80 99 } else if url.Scheme == "https" { 100 port = 443 101 } else { 102 log.Println("Error Adding Monitor: unknown protocol ", url.Scheme) 103 return 104 } 105 } else { 106 port, err = strconv.Atoi(portString) 107 if err != nil { 108 log.Println("Error Adding Monitor: ", err.Error()) 109 return 110 } 111 } 112 113 _, err = service.client.CreateUptimeCheckConfig(service.ctx, &monitoringpb.CreateUptimeCheckConfigRequest{ 114 Parent: "projects/" + service.projectID, 115 UptimeCheckConfig: &monitoringpb.UptimeCheckConfig{ 116 DisplayName: monitor.Name, 117 Resource: &monitoringpb.UptimeCheckConfig_MonitoredResource{ 118 MonitoredResource: &monitoredres.MonitoredResource{ 119 Type: "uptime_url", 120 Labels: map[string]string{ 121 "host": url.Hostname(), 122 }, 123 }, 124 }, 125 CheckRequestType: &monitoringpb.UptimeCheckConfig_HttpCheck_{ 126 HttpCheck: &monitoringpb.UptimeCheckConfig_HttpCheck{ 127 Path: url.Path, 128 Port: int32(port), 129 UseSsl: url.Scheme == "https", 130 }, 131 }, 132 }, 133 }) 134 if err != nil { 135 log.Println("Error Adding Monitor: ", err.Error()) 136 return 137 } 138 139 log.Println("Added monitor for: ", monitor.Name) 140 } 141 142 func (service *MonitorService) Update(monitor models.Monitor) { 143 uptimeCheckConfig, err := service.client.GetUptimeCheckConfig(service.ctx, &monitoringpb.GetUptimeCheckConfigRequest{Name: monitor.ID}) 144 if err != nil { 145 log.Println("Error updating Monitor: ", err.Error()) 146 } 147 148 url, err := url.Parse(monitor.URL) 149 if err != nil { 150 log.Println("Error Adding Monitor: ", err.Error()) 151 return 152 } 153 154 if uptimeCheckConfig.GetMonitoredResource().Labels["host"] != url.Hostname() { 155 log.Println("Error Adding Monitor: URL Host is immutable") 156 return 157 } 158 159 portString := url.Port() 160 var port int 161 if portString == "" { 162 if url.Scheme == "http" { 163 port = 80 164 } else if url.Scheme == "https" { 165 port = 443 166 } else { 167 log.Println("Error Adding Monitor: unknown protocol ", url.Scheme) 168 return 169 } 170 } else { 171 port, err = strconv.Atoi(portString) 172 if err != nil { 173 log.Println("Error Adding Monitor: ", err.Error()) 174 return 175 } 176 } 177 178 uptimeCheckConfig.DisplayName = monitor.Name 179 uptimeCheckConfig.GetHttpCheck().Port = int32(port) 180 uptimeCheckConfig.GetHttpCheck().Path = url.Path 181 182 uptimeCheckConfig, err = service.client.UpdateUptimeCheckConfig(service.ctx, &monitoringpb.UpdateUptimeCheckConfigRequest{ 183 UptimeCheckConfig: uptimeCheckConfig, 184 }) 185 if err != nil { 186 log.Println("Error Adding Monitor: ", err.Error()) 187 return 188 } 189 190 log.Println("Updated Monitor: ", uptimeCheckConfig) 191 } 192 193 func (service *MonitorService) Remove(monitor models.Monitor) { 194 err := service.client.DeleteUptimeCheckConfig(service.ctx, &monitoringpb.DeleteUptimeCheckConfigRequest{ 195 Name: monitor.ID, 196 }) 197 if err != nil { 198 log.Println("Error deleting Monitor: ", err.Error()) 199 return 200 } 201 log.Println("Deleted Monitor: ", monitor.Name) 202 } 203 204 func transformToMonitor(uptimeCheckConfig *monitoringpb.UptimeCheckConfig) (monitor models.Monitor) { 205 isSsl := uptimeCheckConfig.GetHttpCheck().UseSsl 206 path := uptimeCheckConfig.GetHttpCheck().Path 207 port := uptimeCheckConfig.GetHttpCheck().Port 208 host := uptimeCheckConfig.GetMonitoredResource().Labels["host"] 209 210 var scheme string 211 if isSsl { 212 scheme = "https" 213 } else { 214 scheme = "http" 215 } 216 217 if (isSsl && port != 443) || (!isSsl && port != 80) { 218 host = host + ":" + strconv.FormatInt(int64(port), 10) 219 } 220 221 url := url.URL{ 222 Scheme: scheme, 223 Host: host, 224 Path: path, 225 } 226 227 return models.Monitor{ 228 URL: url.String(), 229 Name: uptimeCheckConfig.DisplayName, 230 ID: uptimeCheckConfig.Name, 231 Annotations: map[string]string{}, 232 } 233 }