From a15c2d0feef29b1ae48dcf9c0a98a7419c34d845 Mon Sep 17 00:00:00 2001 From: Chriskery Date: Tue, 7 Jan 2025 21:07:22 +0800 Subject: [PATCH] Adding support for AliCloud monitor --- README.md | 1 + api/v1alpha1/endpointmonitor_types.go | 23 ++ api/v1alpha1/zz_generated.deepcopy.go | 20 ++ ...monitor.stakater.com_endpointmonitors.yaml | 16 + docs/alicloud-configuration.md | 0 examples/configs/test-config-alicloud.yaml | 5 + go.mod | 13 + go.sum | 77 +++++ pkg/controllers/endpointmonitor_controller.go | 8 +- pkg/controllers/endpointmonitor_created.go | 7 +- .../alicloud/alicloud-arms-monitor.go | 299 ++++++++++++++++++ .../alicloud/alicloud-arms-monitor_test.go | 94 ++++++ pkg/monitors/monitor-proxy.go | 3 + 13 files changed, 562 insertions(+), 4 deletions(-) create mode 100644 docs/alicloud-configuration.md create mode 100644 examples/configs/test-config-alicloud.yaml create mode 100644 pkg/monitors/alicloud/alicloud-arms-monitor.go create mode 100644 pkg/monitors/alicloud/alicloud-arms-monitor_test.go diff --git a/README.md b/README.md index cddcf9a1..0d12b319 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Currently we support the following monitors: - [Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/monitor-web-app-availability) ([Additional Config](docs/appinsights-configuration.md)) - [gcloud](https://cloud.google.com/monitoring/uptime-checks) ([Additional Config](docs/gcloud-configuration.md)) - [Grafana](https://grafana.com/grafana/plugins/grafana-synthetic-monitoring-app/) ([Additional Config](docs/grafana-configuration.md)) +- [AliCloud](https://help.aliyun.com/zh/cms/user-guide/site-monitoring/?spm=5176.2020520111.console-base_help.dexternal.4d7866103lMFSV&scm=20140722.S_help%40%40%E6%96%87%E6%A1%A3%40%40416684.S_BB2%40bl%2BRQW%40ag0%2BBB1%40ag0%2Bhot%2Bos0.ID_416684-RL_%E7%AB%99%E7%82%B9%E7%9B%91%E6%8E%A7-LOC_console~UND~help-OR_ser-V_4-P0_0) ([Additional Config](docs/alicloud-configuration.md)) ## Usage diff --git a/api/v1alpha1/endpointmonitor_types.go b/api/v1alpha1/endpointmonitor_types.go index 321127bd..77d404c7 100644 --- a/api/v1alpha1/endpointmonitor_types.go +++ b/api/v1alpha1/endpointmonitor_types.go @@ -75,6 +75,10 @@ type EndpointMonitorSpec struct { // Configuration for Grafana Cloud Monitor Provider // +optional GrafanaConfig *GrafanaConfig `json:"grafanaConfig,omitempty"` + + // Configuration for Alibaba Cloud Monitor Provider + // +optional + AliCloudConfig *AliCloudConfig `json:"aliCloudConfig,omitempty"` } // UptimeRobotConfig defines the configuration for UptimeRobot Monitor Provider @@ -414,6 +418,25 @@ type GrafanaConfig struct { AlertSensitivity string `json:"alertSensitivity,omitempty"` } +type AliCloudConfig struct { + // The type of the site monitoring task. + // + // Valid values: HTTP, PING, TCP, UDP, DNS, SMTP, POP3, and FTP. + // + // > You must create at least one site monitoring task. You must specify all of the `Address`, `TaskName`, and `TaskType` parameters in each request. + // + // example: + // + // HTTP + TaskType string `json:"TaskType,omitempty"` + // The extended options of the protocol that is used by the site monitoring task. The options vary based on the protocol. + // + // example: + // + // {"time_out":5000} + OptionsJson string `json:"optionsJson,omitempty"` +} + // URLSource represents the set of resources to fetch the URL from type URLSource struct { // +optional diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f29f3158..a626e8a5 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -25,6 +25,21 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AliCloudConfig) DeepCopyInto(out *AliCloudConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AliCloudConfig. +func (in *AliCloudConfig) DeepCopy() *AliCloudConfig { + if in == nil { + return nil + } + out := new(AliCloudConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AppInsightsConfig) DeepCopyInto(out *AppInsightsConfig) { *out = *in @@ -152,6 +167,11 @@ func (in *EndpointMonitorSpec) DeepCopyInto(out *EndpointMonitorSpec) { *out = new(GrafanaConfig) (*in).DeepCopyInto(*out) } + if in.AliCloudConfig != nil { + in, out := &in.AliCloudConfig, &out.AliCloudConfig + *out = new(AliCloudConfig) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointMonitorSpec. diff --git a/config/crd/bases/endpointmonitor.stakater.com_endpointmonitors.yaml b/config/crd/bases/endpointmonitor.stakater.com_endpointmonitors.yaml index f7356970..99612e5b 100644 --- a/config/crd/bases/endpointmonitor.stakater.com_endpointmonitors.yaml +++ b/config/crd/bases/endpointmonitor.stakater.com_endpointmonitors.yaml @@ -35,6 +35,22 @@ spec: spec: description: EndpointMonitorSpec defines the desired state of EndpointMonitor properties: + aliCloudConfig: + description: Configuration for Alibaba Cloud Monitor Provider + properties: + TaskType: + description: "The type of the site monitoring task. \n Valid values: + HTTP, PING, TCP, UDP, DNS, SMTP, POP3, and FTP. \n > You must + create at least one site monitoring task. You must specify all + of the `Address`, `TaskName`, and `TaskType` parameters in each + request. \n example: \n HTTP" + type: string + optionsJson: + description: "The extended options of the protocol that is used + by the site monitoring task. The options vary based on the protocol. + \n example: \n {\"time_out\":5000}" + type: string + type: object appInsightsConfig: description: Configuration for AppInsights Monitor Provider properties: diff --git a/docs/alicloud-configuration.md b/docs/alicloud-configuration.md new file mode 100644 index 00000000..e69de29b diff --git a/examples/configs/test-config-alicloud.yaml b/examples/configs/test-config-alicloud.yaml new file mode 100644 index 00000000..1b580941 --- /dev/null +++ b/examples/configs/test-config-alicloud.yaml @@ -0,0 +1,5 @@ +providers: + - name: AliCloud + apiKey: + apiToken: + apiURL: "metrics.cn-qingdao.aliyuncs.com" diff --git a/go.mod b/go.mod index c4b0cca3..c14dbdf0 100644 --- a/go.mod +++ b/go.mod @@ -44,8 +44,19 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect + github.com/alibabacloud-go/cms-20190101/v9 v9.1.3 // indirect + github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 // indirect + github.com/alibabacloud-go/debug v1.0.1 // indirect + github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect + github.com/alibabacloud-go/openapi-util v0.1.1 // indirect + github.com/alibabacloud-go/tea v1.2.2 // indirect + github.com/alibabacloud-go/tea-utils/v2 v2.0.6 // indirect + github.com/alibabacloud-go/tea-xml v1.1.3 // indirect + github.com/aliyun/credentials-go v1.3.10 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/clbanning/mxj/v2 v2.5.5 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dimchansky/utfbom v1.1.0 // indirect github.com/emicklei/go-restful v2.16.0+incompatible // indirect @@ -81,6 +92,7 @@ require ( github.com/prometheus/common v0.46.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.6.0 // indirect @@ -98,6 +110,7 @@ require ( google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.24.0 // indirect k8s.io/component-base v0.24.0 // indirect diff --git a/go.sum b/go.sum index 2222301b..e69c3e1a 100644 --- a/go.sum +++ b/go.sum @@ -92,6 +92,48 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g= +github.com/alibabacloud-go/cms-20190101/v9 v9.1.3 h1:SdnidmdbluLY9Z4CYuRr2zKiwcC2j5OCwu582rGzsKM= +github.com/alibabacloud-go/cms-20190101/v9 v9.1.3/go.mod h1:VYw/qh2CjRFGZ9T2Re8CThOpMB0nzidiZc0NidDDJ28= +github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8= +github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ= +github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= +github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= +github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg= +github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q= +github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= +github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= +github.com/alibabacloud-go/openapi-util v0.1.1 h1:ujGErJjG8ncRW6XtBBMphzHTvCxn4DjrVw4m04HsS28= +github.com/alibabacloud-go/openapi-util v0.1.1/go.mod h1:/UehBSE2cf1gYT43GV4E+RxTdLRzURImCYY0aRmlXpw= +github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg= +github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU= +github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= +github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I= +github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= +github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4= +github.com/alibabacloud-go/tea-utils/v2 v2.0.6 h1:ZkmUlhlQbaDC+Eba/GARMPy6hKdCLiSke5RsN5LcyQ0= +github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= +github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= +github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= +github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= +github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= +github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= +github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA= +github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/antoineaugusti/updown v0.0.0-20190412074625-d590ab97f115 h1:zJT4IRToZQDCLmeoqL8csL/J5aSmq4dFzXrTJsrPrz8= @@ -123,6 +165,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E= +github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -327,6 +371,7 @@ github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTV github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -541,6 +586,7 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -581,6 +627,9 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -588,6 +637,7 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -659,11 +709,18 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -743,6 +800,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -759,7 +817,12 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -829,6 +892,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -866,14 +930,22 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -888,6 +960,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= @@ -946,6 +1019,7 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -1108,6 +1182,9 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/pkg/controllers/endpointmonitor_controller.go b/pkg/controllers/endpointmonitor_controller.go index b81f5838..84e777ab 100644 --- a/pkg/controllers/endpointmonitor_controller.go +++ b/pkg/controllers/endpointmonitor_controller.go @@ -59,9 +59,6 @@ type EndpointMonitorReconciler struct { func (r *EndpointMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Log.WithValues("endpointmonitor", req.NamespacedName) - // Fetch the EndpointMonitor instance - instance := &endpointmonitorv1alpha1.EndpointMonitor{} - var monitorName string format, err := util.GetNameTemplateFormat(config.GetControllerConfig().MonitorNameTemplate) if err != nil { @@ -71,6 +68,8 @@ func (r *EndpointMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Requ monitorName = fmt.Sprintf(format, req.Name, req.Namespace) } + // Fetch the EndpointMonitor instance + instance := &endpointmonitorv1alpha1.EndpointMonitor{} err = r.Get(context.TODO(), req.NamespacedName, instance) if err != nil { if errors.IsNotFound(err) { @@ -142,6 +141,9 @@ func (r *EndpointMonitorReconciler) GetMonitorOfType(spec endpointmonitorv1alpha if spec.GrafanaConfig != nil { return r.GetMonitorServiceOfType(monitors.TypeGrafana) } + if spec.AliCloudConfig != nil { + return r.GetMonitorServiceOfType(monitors.TypeAliCloud) + } // If none of the above, return the first monitor service return r.MonitorServices[0] } diff --git a/pkg/controllers/endpointmonitor_created.go b/pkg/controllers/endpointmonitor_created.go index bc00427e..b89cdd6f 100644 --- a/pkg/controllers/endpointmonitor_created.go +++ b/pkg/controllers/endpointmonitor_created.go @@ -9,7 +9,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -func (r *EndpointMonitorReconciler) handleCreate(request reconcile.Request, instance *endpointmonitorv1alpha1.EndpointMonitor, monitorName string, monitorService *monitors.MonitorServiceProxy) error { +func (r *EndpointMonitorReconciler) handleCreate( + request reconcile.Request, + instance *endpointmonitorv1alpha1.EndpointMonitor, + monitorName string, + monitorService *monitors.MonitorServiceProxy, +) error { log := r.Log.WithValues("Namespace", instance.ObjectMeta.Namespace) log.Info("Creating Monitor: "+monitorName, "MonitorType", monitorService.GetType()) diff --git a/pkg/monitors/alicloud/alicloud-arms-monitor.go b/pkg/monitors/alicloud/alicloud-arms-monitor.go new file mode 100644 index 00000000..03382b97 --- /dev/null +++ b/pkg/monitors/alicloud/alicloud-arms-monitor.go @@ -0,0 +1,299 @@ +package alicloud + +import ( + "encoding/json" + "errors" + "fmt" + cms20190101 "github.com/alibabacloud-go/cms-20190101/v9/client" + openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" + util "github.com/alibabacloud-go/tea-utils/v2/service" + "github.com/alibabacloud-go/tea/tea" + "github.com/karlderkaefer/pingdom-golang-client/pkg/pingdom/openapi/ptr" + endpointmonitorv1alpha1 "github.com/stakater/IngressMonitorController/v2/api/v1alpha1" + "github.com/stakater/IngressMonitorController/v2/pkg/config" + "github.com/stakater/IngressMonitorController/v2/pkg/models" + "github.com/stakater/IngressMonitorController/v2/pkg/monitors" + "reflect" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "strings" +) + +var log = logf.Log.WithName("AliCloud") + +var _ monitors.MonitorService = &AliCloudMonitorService{} + +// AliCloudMonitorService struct contains parameters required by AliCloud go client +type AliCloudMonitorService struct { + accessKey string + secretKey string + endpoint string + client *cms20190101.Client +} + +func (monitor *AliCloudMonitorService) Equal(oldMonitor models.Monitor, newMonitor models.Monitor) bool { + return reflect.DeepEqual(oldMonitor, newMonitor) +} + +// Setup method will initialize a AliCloud's go client object by using the configuration parameters +func (monitor *AliCloudMonitorService) Setup(confProvider config.Provider) { + + // initializeCustomLog(os.Stdout) + log.Info("AliCloud monitor's Setup has been called. AliCloud monitor initializing") + + // AliCloud go client apiKey + monitor.accessKey = confProvider.ApiKey + monitor.secretKey = confProvider.ApiToken + monitor.endpoint = monitor.formatEndpoint(confProvider.ApiURL) + + // creating AliCloud go client + client, err := monitor.newClient() + if err != nil { + panic(fmt.Sprintf("Unable to initialize AliCloud client: %v", err)) + } + monitor.client = client + log.Info("AliCloud monitor has been initialized") +} + +// GetAll function will return all monitors (AliCloud checks) object in an array +func (monitor *AliCloudMonitorService) GetAll() []models.Monitor { + log.Info("AliCloud monitor's GetAll method has been called") + + describeSiteMonitorListRequest := &cms20190101.DescribeSiteMonitorListRequest{} + request, err := monitor.getByListRequest(describeSiteMonitorListRequest) + if err != nil { + log.Error(err, "failed to get AliCloud checks", "describeSiteMonitorListRequest", describeSiteMonitorListRequest.String()) + } + return request +} + +func (monitor *AliCloudMonitorService) getByListRequest(describeSiteMonitorListRequest *cms20190101.DescribeSiteMonitorListRequest) ([]models.Monitor, error) { + var allMonitors []models.Monitor + var listResult *cms20190101.DescribeSiteMonitorListResponse + runtime := &util.RuntimeOptions{} + tryErr := func() (err error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + err = r + } + }() + listResult, err = monitor.client.DescribeSiteMonitorListWithOptions(describeSiteMonitorListRequest, runtime) + return err + }() + + if tryErr != nil { + return allMonitors, monitor.formatTryError(tryErr) + } + + if listResult.Body == nil || listResult.Body.TotalCount == nil || listResult.Body.SiteMonitors == nil { + return allMonitors, fmt.Errorf("listResult.Body.SiteMonitors is nil") + } + + // populating a allMonitors slice using the AliCloudChecks objects given in AliCloudChecks slice + for _, aliCloudCheck := range listResult.Body.SiteMonitors.SiteMonitor { + newMonitor := models.Monitor{ + URL: *aliCloudCheck.Address, + Name: *aliCloudCheck.TaskName, + ID: *aliCloudCheck.TaskId, + } + allMonitors = append(allMonitors, newMonitor) + } + return allMonitors, nil +} + +func (monitor *AliCloudMonitorService) formatTryError(tryErr error) error { + var err = &tea.SDKError{} + if _t, ok := tryErr.(*tea.SDKError); ok { + err = _t + } else { + err.Message = tea.String(tryErr.Error()) + } + result, assertErr := util.AssertAsString(err.Message) + if assertErr == nil { + return errors.New(tea.StringValue(result)) + } + return errors.New(err.Error()) +} + +// GetByName function will return a monitor(AliCloud check) object based on the name provided +func (monitor *AliCloudMonitorService) GetByName(monitorName string) (*models.Monitor, error) { + + log.Info("AliCloud monitor's GetByName method has been called") + + describeSiteMonitorListRequest := &cms20190101.DescribeSiteMonitorListRequest{ + Keyword: ptr.String(monitorName), + } + byListRequest, err := monitor.getByListRequest(describeSiteMonitorListRequest) + if err != nil { + return nil, err + } + if len(byListRequest) < 1 { + return nil, nil + } + return &byListRequest[0], nil +} + +func (monitor *AliCloudMonitorService) getSiteMonitorCreateInstance(aliCloudMonitor models.Monitor) *cms20190101.CreateSiteMonitorRequest { + singleTask := &cms20190101.CreateSiteMonitorRequest{ + Address: tea.String(aliCloudMonitor.URL), + TaskName: tea.String(aliCloudMonitor.Name), + } + if aliCloudMonitor.Config != nil { + providerConfig, ok := aliCloudMonitor.Config.(*endpointmonitorv1alpha1.AliCloudConfig) + if !ok { + panic(fmt.Errorf("unable to locate %v monitor", aliCloudMonitor.Name)) + } + singleTask.TaskType = tea.String(providerConfig.TaskType) + singleTask.OptionsJson = tea.String(providerConfig.OptionsJson) + } + + if singleTask.TaskType == nil { + singleTask.TaskType = ptr.String("HTTP") + } + return singleTask +} + +func (monitor *AliCloudMonitorService) getSiteMonitorUpdateInstance(aliCloudMonitor models.Monitor) *cms20190101.ModifySiteMonitorRequest { + singleTask := &cms20190101.ModifySiteMonitorRequest{ + Address: tea.String(aliCloudMonitor.URL), + TaskName: tea.String(aliCloudMonitor.Name), + TaskId: ptr.String(aliCloudMonitor.ID), + } + if aliCloudMonitor.Config != nil { + providerConfig, ok := aliCloudMonitor.Config.(*endpointmonitorv1alpha1.AliCloudConfig) + if !ok { + panic(fmt.Errorf("unable to locate %v monitor", aliCloudMonitor.Name)) + } + singleTask.OptionsJson = tea.String(providerConfig.OptionsJson) + } + return singleTask +} + +// Add function method will add a monitor (AliCloud check) +func (monitor *AliCloudMonitorService) Add(aliCloudMonitor models.Monitor) { + + log.Info("AliCloud monitor's Add method has been called") + + createInstance := monitor.getSiteMonitorCreateInstance(aliCloudMonitor) + runtime := &util.RuntimeOptions{} + var createResult *cms20190101.CreateSiteMonitorResponse + tryErr := func() (err error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + err = r + } + }() + createResult, err = monitor.client.CreateSiteMonitorWithOptions(createInstance, runtime) + return err + }() + if tryErr != nil { + log.Error(monitor.formatTryError(tryErr), "failed to create AliCloud check", "createInstance", createInstance.String()) + return + } + + if createResult.Body == nil { + log.Error(errors.New("createResult is nil"), "createResult is nil") + return + } + + if createResult.Body.Success == nil || *createResult.Body.Success != "true" { + bodyJson, _ := json.Marshal(createResult.Body) + log.Error(errors.New("failed to create AliCloud check"), "failed to create AliCloud check", "body", bodyJson) + return + } + log.Info("Monitor addition request has been completed", "createResult", createResult.Body.CreateResultList) +} + +// Update method will update a monitor (AliCloud check) +func (monitor *AliCloudMonitorService) Update(aliCloudMonitor models.Monitor) { + + log.Info("AliCloud's Update method has been called") + + getInstance := monitor.getSiteMonitorUpdateInstance(aliCloudMonitor) + runtime := &util.RuntimeOptions{} + var updateResult *cms20190101.ModifySiteMonitorResponse + tryErr := func() (err error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + err = r + } + }() + updateResult, err = monitor.client.ModifySiteMonitorWithOptions(getInstance, runtime) + return err + }() + if tryErr != nil { + log.Error(monitor.formatTryError(tryErr), "failed to update AliCloud check", "getInstance", getInstance.String()) + return + } + + if updateResult.Body == nil { + log.Error(errors.New("createResult is nil"), "createResult is nil") + return + } + + if updateResult.Body.Success == nil || *updateResult.Body.Success != "true" { + bodyJson, _ := json.Marshal(updateResult.Body) + log.Error(errors.New("failed to update AliCloud check"), "failed to create AliCloud check", "body", bodyJson) + return + } + log.Info("AliCloud's check Update request has been completed", "updateResult", updateResult.String()) +} + +// Remove method will remove a monitor (AliCloud check) +func (monitor *AliCloudMonitorService) Remove(aliCloudMonitor models.Monitor) { + + log.Info("AliCloud's Remove method has been called") + + deleteSiteMonitorsRequest := &cms20190101.DeleteSiteMonitorsRequest{ + TaskIds: tea.String(aliCloudMonitor.ID), + } + var deleteResult *cms20190101.DeleteSiteMonitorsResponse + runtime := &util.RuntimeOptions{} + tryErr := func() (err error) { + defer func() { + if r := tea.Recover(recover()); r != nil { + err = r + } + }() + deleteResult, err = monitor.client.DeleteSiteMonitorsWithOptions(deleteSiteMonitorsRequest, runtime) + return err + }() + + if tryErr != nil { + log.Error(monitor.formatTryError(tryErr), "failed to delete AliCloud check", "deleteSiteMonitorsRequest", deleteSiteMonitorsRequest.String()) + return + } + if deleteResult.Body == nil { + log.Error(errors.New("createResult is nil"), "createResult is nil") + return + } + + if deleteResult.Body.Success == nil || *deleteResult.Body.Success != "true" { + bodyJson, _ := json.Marshal(deleteResult.Body) + log.Error(errors.New("failed to delete AliCloud check"), "failed to create AliCloud check", "body", bodyJson) + return + } + log.Info("AliCloud's check Remove request has been completed", "deleteResult", deleteResult.Body) +} + +func (monitor *AliCloudMonitorService) newClient() (*cms20190101.Client, error) { + cfg := &openapi.Config{ + AccessKeyId: tea.String(monitor.accessKey), + AccessKeySecret: tea.String(monitor.secretKey), + } + // Endpoint refers to: https://api.aliyun.com/product/Cms + cfg.Endpoint = tea.String(monitor.endpoint) + return cms20190101.NewClient(cfg) +} + +func (monitor *AliCloudMonitorService) formatEndpoint(url string) string { + if strings.Trim(url, " ") == "" { + return "metrics.cn-qingdao.aliyuncs.com" + } + if strings.HasPrefix(url, "http://") { + return strings.Split(url, "http://")[1] + } + if strings.HasPrefix(url, "https://") { + return strings.Split(url, "https://")[1] + } + return url +} diff --git a/pkg/monitors/alicloud/alicloud-arms-monitor_test.go b/pkg/monitors/alicloud/alicloud-arms-monitor_test.go new file mode 100644 index 00000000..e93cdc55 --- /dev/null +++ b/pkg/monitors/alicloud/alicloud-arms-monitor_test.go @@ -0,0 +1,94 @@ +package alicloud + +import ( + "fmt" + "github.com/stakater/IngressMonitorController/v2/pkg/monitors" + "github.com/stretchr/testify/assert" + "testing" + + "github.com/stakater/IngressMonitorController/v2/pkg/config" + "github.com/stakater/IngressMonitorController/v2/pkg/models" + "github.com/stakater/IngressMonitorController/v2/pkg/util" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +func init() { + // To allow normal logging to be printed if tests fails + // Dev mode is an extra feature to make output more readable + ctrl.SetLogger(zap.New(zap.UseDevMode(true))) +} + +func TestAddMonitorWithCorrectValues(t *testing.T) { + config := config.GetControllerConfigTest() + + service := AliCloudMonitorService{} + provider := util.GetProviderWithName(config, monitors.TypeAliCloud) + if provider == nil { + // TODO: Currently forcing to pass the test as we dont have Pingdom account to test + // Fail this case in future when have a valid Pingdom account + log.Error(nil, "Failed to find provider") + return + } + service.Setup(*provider) + m := models.Monitor{Name: "AliCloud-test", URL: "metrics.cn-qingdao.aliyuncs.com"} + service.Add(m) + + mRes, err := service.GetByName("AliCloud-test") + assert.Nil(t, err) + assert.NotNil(t, mRes) + + if mRes.Name != m.Name || mRes.URL != m.URL { + t.Errorf("URL and name should be the same. request: %+v response: %+v", m, mRes) + return + } + + // Cleanup + service.Remove(*mRes) + monitor, err := service.GetByName(mRes.Name) + assert.Nil(t, monitor, fmt.Sprintf("Monitor should've been deleted %v %v", monitor, err)) +} + +func TestUpdateMonitorWithCorrectValues(t *testing.T) { + config := config.GetControllerConfigTest() + + service := AliCloudMonitorService{} + + provider := util.GetProviderWithName(config, monitors.TypeAliCloud) + if provider == nil { + // TODO: Currently forcing to pass the test as we dont have Pingdom account to test + // Fail this case in future when have a valid Pingdom account + log.Error(nil, "Failed to find provider") + return + } + service.Setup(*provider) + + // Create initial record + m := models.Monitor{Name: "AliCloud-test", URL: "https://aliCloud.com"} + service.Add(m) + + mRes, err := service.GetByName("AliCloud-test") + assert.Nil(t, err) + assert.NotNil(t, mRes) + + if mRes.Name != m.Name || mRes.URL != m.URL { + t.Errorf("URL and name should be the same. request: %+v response: %+v", m, mRes) + } + + targetUrl := "https://facebook.com" + // Update the record + mRes.URL = targetUrl + + service.Update(*mRes) + + mRes, err = service.GetByName("AliCloud-test") + assert.Nil(t, err) + if mRes.Name != m.Name || mRes.URL != targetUrl { + t.Errorf("URL and name should be the same. request: %+v response: %+v", m, mRes) + } + + // Cleanup + service.Remove(*mRes) + monitor, err := service.GetByName(mRes.Name) + assert.Nil(t, monitor, fmt.Sprintf("Monitor should've been deleted %v %v", monitor, err)) +} diff --git a/pkg/monitors/monitor-proxy.go b/pkg/monitors/monitor-proxy.go index 6875846a..90f7d45a 100644 --- a/pkg/monitors/monitor-proxy.go +++ b/pkg/monitors/monitor-proxy.go @@ -28,6 +28,7 @@ const ( TypeAppInsights = "AppInsights" TypeGCloud = "gcloud" TypeGrafana = "Grafana" + TypeAliCloud = "AliCloud" ) type MonitorServiceProxy struct { @@ -87,6 +88,8 @@ func (mp *MonitorServiceProxy) ExtractConfig(spec endpointmonitorv1alpha1.Endpoi config = spec.GCloudConfig case TypeGrafana: config = spec.GrafanaConfig + case TypeAliCloud: + config = spec.AliCloudConfig default: return config }