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..19bca15b --- /dev/null +++ b/docs/alicloud-configuration.md @@ -0,0 +1,25 @@ +# Gcloud Configuration + +You can configure AliCloud Cloud Monitoring Uptime Checks as a Ingress Monitor by using below configuration: + + +| Key | Description | +| -------------|------------------------------------------------------------------------------------| +| name | Name of the provider (e.g. AliCloud) | +| apiKey | Access Key ID (AKID): This is a unique identifier for your Alibaba Cloud account. It is used in conjunction with the Access Key Secret to sign requests.| +| apiToken | Access Key Secret (AKSK): This is a secret key associated with the Access Key ID. It is used to sign requests to ensure that they are sent by a legitimate user. | +| apiURL | `apiUrl` refers to: https://api.aliyun.com/product/Cms | + +When you create an Alibaba Cloud account, you are provided with an Access Key ID (AKID) and an Access Key Secret (AKSK). These credentials are used to sign requests to Alibaba Cloud APIs, ensuring that the requests are securely authenticated. + +AccessKey ID and AccessKey Secret are your security credentials to access API of Alibaba Cloud, have full access to your account. Keep the AccessKey confidential. + +**Example Configuration:** + +```yaml +providers: + - name: AliCloud + apiKey: + apiToken: + apiURL: "metrics.cn-qingdao.aliyuncs.com" +``` 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 }