@@ -19,7 +19,6 @@ package scalers
1919import (
2020 "context"
2121 "fmt"
22- "strconv"
2322 "strings"
2423 "time"
2524
@@ -48,18 +47,77 @@ type azureLogAnalyticsScaler struct {
4847}
4948
5049type azureLogAnalyticsMetadata struct {
51- tenantID string
52- clientID string
53- clientSecret string
54- workspaceID string
55- podIdentity kedav1alpha1.AuthPodIdentity
56- query string
57- threshold float64
58- activationThreshold float64
59- triggerIndex int
60- cloud azcloud.Configuration
61- unsafeSsl bool
62- timeout time.Duration // custom HTTP client timeout
50+ TenantID string `keda:"name=tenantId, order=authParams;triggerMetadata;resolvedEnv"`
51+ ClientID string `keda:"name=clientId, order=authParams;triggerMetadata;resolvedEnv"`
52+ ClientSecret string `keda:"name=clientSecret, order=authParams;triggerMetadata;resolvedEnv"`
53+ WorkspaceID string `keda:"name=workspaceId, order=authParams;triggerMetadata;resolvedEnv"`
54+ PodIdentity kedav1alpha1.AuthPodIdentity
55+ Query string `keda:"name=query, order=triggerMetadata"`
56+ Threshold float64 `keda:"name=threshold, order=triggerMetadata"`
57+ ActivationThreshold float64 `keda:"name=activationThreshold, order=triggerMetadata, default=0"`
58+ LogAnalyticsResourceURL string `keda:"name=logAnalyticsResourceURL, order=triggerMetadata, optional"`
59+ TriggerIndex int
60+ CloudName string `keda:"name=cloud, order=triggerMetadata, default=azurePublicCloud"`
61+ Cloud azcloud.Configuration
62+ UnsafeSsl bool `keda:"name=unsafeSsl, order=triggerMetadata, default=false"`
63+ MillisecondTimeout int32 `keda:"name=timeout, order=triggerMetadata, optional"`
64+ Timeout time.Duration // custom HTTP client timeout
65+ }
66+
67+ func (m * azureLogAnalyticsMetadata ) Validate () error {
68+ missingParameter := ""
69+
70+ switch m .PodIdentity .Provider {
71+ case "" , kedav1alpha1 .PodIdentityProviderNone :
72+ if m .TenantID == "" {
73+ missingParameter = "tenantId"
74+ }
75+ if m .ClientID == "" {
76+ missingParameter = "clientId"
77+ }
78+ if m .ClientSecret == "" {
79+ missingParameter = "clientSecret"
80+ }
81+ case kedav1alpha1 .PodIdentityProviderAzureWorkload :
82+ break
83+ default :
84+ return fmt .Errorf ("error parsing metadata. Details: Log Analytics Scaler doesn't support pod identity %s" , m .PodIdentity .Provider )
85+ }
86+
87+ if m .WorkspaceID == "" {
88+ missingParameter = "workspaceId"
89+ }
90+ if m .Query == "" {
91+ missingParameter = "query"
92+ }
93+
94+ m .Cloud = azcloud .AzurePublic
95+ if strings .EqualFold (m .CloudName , azure .PrivateCloud ) {
96+ if m .LogAnalyticsResourceURL != "" {
97+ m .Cloud .Services [azquery .ServiceNameLogs ] = azcloud.ServiceConfiguration {
98+ Endpoint : fmt .Sprintf ("%s/v1" , m .LogAnalyticsResourceURL ),
99+ Audience : m .LogAnalyticsResourceURL ,
100+ }
101+ } else {
102+ return fmt .Errorf ("logAnalyticsResourceURL must be provided for %s cloud type" , azure .PrivateCloud )
103+ }
104+ } else if resource , ok := azure .AzureClouds [strings .ToUpper (m .CloudName )]; ok {
105+ m .Cloud = resource
106+ } else {
107+ return fmt .Errorf ("there is no cloud environment matching the name %s" , m .CloudName )
108+ }
109+
110+ if m .MillisecondTimeout > 0 {
111+ m .Timeout = time .Duration (m .MillisecondTimeout ) * time .Millisecond
112+ } else if m .MillisecondTimeout < 0 {
113+ return fmt .Errorf ("timeout must be greater than 0" )
114+ }
115+
116+ if missingParameter != "" {
117+ return fmt .Errorf ("error parsing metadata. Details: %s was not found in metadata. Check your ScaledObject configuration" , missingParameter )
118+ }
119+
120+ return nil
63121}
64122
65123// NewAzureLogAnalyticsScaler creates a new Azure Log Analytics Scaler
@@ -96,7 +154,7 @@ func CreateAzureLogsClient(config *scalersconfig.ScalerConfig, meta *azureLogAna
96154 var err error
97155 switch config .PodIdentity .Provider {
98156 case "" , kedav1alpha1 .PodIdentityProviderNone :
99- creds , err = azidentity .NewClientSecretCredential (meta .tenantID , meta .clientID , meta .clientSecret , nil )
157+ creds , err = azidentity .NewClientSecretCredential (meta .TenantID , meta .ClientID , meta .ClientSecret , nil )
100158 case kedav1alpha1 .PodIdentityProviderAzureWorkload :
101159 creds , err = azure .NewChainedCredential (logger , config .PodIdentity )
102160 default :
@@ -107,8 +165,8 @@ func CreateAzureLogsClient(config *scalersconfig.ScalerConfig, meta *azureLogAna
107165 }
108166 client , err := azquery .NewLogsClient (creds , & azquery.LogsClientOptions {
109167 ClientOptions : policy.ClientOptions {
110- Transport : kedautil .CreateHTTPClient (meta .timeout , meta .unsafeSsl ),
111- Cloud : meta .cloud ,
168+ Transport : kedautil .CreateHTTPClient (meta .Timeout , meta .UnsafeSsl ),
169+ Cloud : meta .Cloud ,
112170 },
113171 })
114172 if err != nil {
@@ -118,124 +176,15 @@ func CreateAzureLogsClient(config *scalersconfig.ScalerConfig, meta *azureLogAna
118176}
119177
120178func parseAzureLogAnalyticsMetadata (config * scalersconfig.ScalerConfig ) (* azureLogAnalyticsMetadata , error ) {
121- meta := azureLogAnalyticsMetadata {}
122- switch config .PodIdentity .Provider {
123- case "" , kedav1alpha1 .PodIdentityProviderNone :
124- // Getting tenantId
125- tenantID , err := getParameterFromConfig (config , "tenantId" , true )
126- if err != nil {
127- return nil , err
128- }
129- meta .tenantID = tenantID
130-
131- // Getting clientId
132- clientID , err := getParameterFromConfig (config , "clientId" , true )
133- if err != nil {
134- return nil , err
135- }
136- meta .clientID = clientID
137-
138- // Getting clientSecret
139- clientSecret , err := getParameterFromConfig (config , "clientSecret" , true )
140- if err != nil {
141- return nil , err
142- }
143- meta .clientSecret = clientSecret
144-
145- meta .podIdentity = config .PodIdentity
146- case kedav1alpha1 .PodIdentityProviderAzureWorkload :
147- meta .podIdentity = config .PodIdentity
148- default :
149- return nil , fmt .Errorf ("error parsing metadata. Details: Log Analytics Scaler doesn't support pod identity %s" , config .PodIdentity .Provider )
150- }
151-
152- // Getting workspaceId
153- workspaceID , err := getParameterFromConfig (config , "workspaceId" , true )
154- if err != nil {
155- return nil , err
156- }
157- meta .workspaceID = workspaceID
158-
159- // Getting query, observe that we dont check AuthParams for query
160- query , err := getParameterFromConfig (config , "query" , false )
161- if err != nil {
162- return nil , err
163- }
164- meta .query = query
165-
166- // Getting threshold, observe that we don't check AuthParams for threshold
167- val , err := getParameterFromConfig (config , "threshold" , false )
168- if err != nil {
169- if config .AsMetricSource {
170- val = "0"
171- } else {
172- return nil , err
173- }
174- }
175- threshold , err := strconv .ParseFloat (val , 64 )
176- if err != nil {
177- return nil , fmt .Errorf ("error parsing metadata. Details: can't parse threshold. Inner Error: %w" , err )
178- }
179- meta .threshold = threshold
180-
181- // Getting activationThreshold
182- meta .activationThreshold = 0
183- val , err = getParameterFromConfig (config , "activationThreshold" , false )
184- if err == nil {
185- activationThreshold , err := strconv .ParseFloat (val , 64 )
186- if err != nil {
187- return nil , fmt .Errorf ("error parsing metadata. Details: can't parse threshold. Inner Error: %w" , err )
188- }
189- meta .activationThreshold = activationThreshold
190- }
191- meta .triggerIndex = config .TriggerIndex
192-
193- meta .cloud = azcloud .AzurePublic
194- if cloud , ok := config .TriggerMetadata ["cloud" ]; ok {
195- if strings .EqualFold (cloud , azure .PrivateCloud ) {
196- if resource , ok := config .TriggerMetadata ["logAnalyticsResourceURL" ]; ok && resource != "" {
197- meta .cloud .Services [azquery .ServiceNameLogs ] = azcloud.ServiceConfiguration {
198- Endpoint : fmt .Sprintf ("%s/v1" , resource ),
199- Audience : resource ,
200- }
201- } else {
202- return nil , fmt .Errorf ("logAnalyticsResourceURL must be provided for %s cloud type" , azure .PrivateCloud )
203- }
204- } else if resource , ok := azure .AzureClouds [strings .ToUpper (cloud )]; ok {
205- meta .cloud = resource
206- } else {
207- return nil , fmt .Errorf ("there is no cloud environment matching the name %s" , cloud )
208- }
209- }
210-
211- // Getting unsafeSsl, observe that we don't check AuthParams for unsafeSsl
212- meta .unsafeSsl = false
213- unsafeSslVal , err := getParameterFromConfig (config , "unsafeSsl" , false )
214- if err == nil {
215- unsafeSsl , err := strconv .ParseBool (unsafeSslVal )
216- if err != nil {
217- return nil , fmt .Errorf ("error parsing metadata. Details: can't parse unsafeSsl. Inner Error: %w" , err )
218- }
219- meta .unsafeSsl = unsafeSsl
220- }
221-
222- // Resolve HTTP client timeout
223- meta .timeout = config .GlobalHTTPTimeout
224- timeoutVal , err := getParameterFromConfig (config , "timeout" , false )
225- if err == nil {
226- timeout , err := strconv .Atoi (timeoutVal )
227- if err != nil {
228- return nil , fmt .Errorf ("unable to parse timeout: %w" , err )
229- }
230-
231- if timeout <= 0 {
232- return nil , fmt .Errorf ("timeout must be greater than 0: %w" , err )
233- }
234-
235- meta .timeout = time .Duration (timeout ) * time .Millisecond
179+ meta := & azureLogAnalyticsMetadata {}
180+ meta .TriggerIndex = config .TriggerIndex
181+ meta .Timeout = config .GlobalHTTPTimeout
182+ meta .PodIdentity = config .PodIdentity
183+ if err := config .TypedConfig (meta ); err != nil {
184+ return nil , fmt .Errorf ("error parsing azure loganalytics metadata: %w" , err )
236185 }
237186
238- return & meta , nil
187+ return meta , nil
239188}
240189
241190// getParameterFromConfig gets the parameter from the configs, if checkAuthParams is true
@@ -254,9 +203,9 @@ func getParameterFromConfig(config *scalersconfig.ScalerConfig, parameter string
254203func (s * azureLogAnalyticsScaler ) GetMetricSpecForScaling (context.Context ) []v2.MetricSpec {
255204 externalMetric := & v2.ExternalMetricSource {
256205 Metric : v2.MetricIdentifier {
257- Name : GenerateMetricNameWithIndex (s .metadata .triggerIndex , kedautil .NormalizeString (fmt .Sprintf ("%s-%s" , "azure-log-analytics" , s .metadata .workspaceID ))),
206+ Name : GenerateMetricNameWithIndex (s .metadata .TriggerIndex , kedautil .NormalizeString (fmt .Sprintf ("%s-%s" , "azure-log-analytics" , s .metadata .WorkspaceID ))),
258207 },
259- Target : GetMetricTargetMili (s .metricType , s .metadata .threshold ),
208+ Target : GetMetricTargetMili (s .metricType , s .metadata .Threshold ),
260209 }
261210 metricSpec := v2.MetricSpec {External : externalMetric , Type : externalMetricType }
262211 return []v2.MetricSpec {metricSpec }
@@ -272,16 +221,16 @@ func (s *azureLogAnalyticsScaler) GetMetricsAndActivity(ctx context.Context, met
272221
273222 metric := GenerateMetricInMili (metricName , val )
274223
275- return []external_metrics.ExternalMetricValue {metric }, val > s .metadata .activationThreshold , nil
224+ return []external_metrics.ExternalMetricValue {metric }, val > s .metadata .ActivationThreshold , nil
276225}
277226
278227func (s * azureLogAnalyticsScaler ) Close (context.Context ) error {
279228 return nil
280229}
281230
282231func (s * azureLogAnalyticsScaler ) getMetricData (ctx context.Context ) (float64 , error ) {
283- response , err := s .client .QueryWorkspace (ctx , s .metadata .workspaceID , azquery.Body {
284- Query : & s .metadata .query ,
232+ response , err := s .client .QueryWorkspace (ctx , s .metadata .WorkspaceID , azquery.Body {
233+ Query : & s .metadata .Query ,
285234 }, nil )
286235 if err != nil {
287236 return - 1 , err
0 commit comments